1. Redis List Fundamentals
1.1.What is a Redis List?
What is a Redis List?
A Redis List is an ordered collection of strings, sorted by insertion order.
Key characteristics:
- Maximum length: elements
- Operations on both ends are
- Accessed by index with complexity
- Perfect for queues, stacks, and message processing
1.2.Internal Implementation
Internal Implementation
Redis Lists use different encodings based on size to optimize memory usage:
Small Lists (Listpack). When a list is small, Redis implements it using a compact data structure called listpack (or ziplist in Redis < 7.0). This encoding:
- Stores all elements in a single contiguous block of memory
- Minimizes memory overhead (no pointers between elements)
- Faster cache locality for small lists
- Automatically used when both conditions are met:
- List has fewer than 512 elements (configurable via
list-max-listpack-entries) - Each element is smaller than 64 bytes (configurable via
list-max-listpack-value)
- List has fewer than 512 elements (configurable via
Large Lists (Quicklist). When thresholds are exceeded, Redis converts to a quicklist:
- Hybrid structure: doubly-linked list of listpacks
- Balances memory efficiency with performance
- Each node in the quicklist is a listpack
- Allows efficient insertion/deletion at both ends
Simply put:
-
Internally redis use
Listpack(an array of entries with various sizes) andLinkedListinterchangeably. The underlying reason is that for small list pointers is even bigger than the internal data. -
Plus
LinkedListcannot fully utilize the cache feteched from memory into CPU: looping over pointer is highly inefficient.
1.3.Create and Add to Lists
Create and Add to Lists
Redis Lists are created automatically when you add the first element (on the other hand, we cannot create an empty list):
LPUSH= Left push (add to head)RPUSH= Right push (add to tail)
1.4.Read from Lists
Read from Lists
1.5.Remove from Lists
Remove from Lists
2. BLMOVE - Reliable List-Based Message Queue
BLMOVE - Reliable List-Based Message Queue2.1.On BLMOVE
On BLMOVE
2.1.1.What is it?
What is it?
BLMOVE (Blocking List Move) is a Redis command that atomically moves an element from one list to another. It's the blocking version of LMOVE, meaning it will wait for an element to be available if the source list is empty.
Syntax:
Parameters:
source- The list to move fromdestination- The list to move to- First
LEFT|RIGHT- Which end to pop from source (LEFT = head, RIGHT = tail) - Second
LEFT|RIGHT- Which end to push to destination timeout- Maximum seconds to wait (0 = wait forever)
2.1.2.Why BLMOVE?
Why BLMOVE?
Problem it solves. When building a message queue with Redis Lists, we face a critical issue: what happens if a consumer crashes while processing a message?
Without BLMOVE (using RPOP):
- Now processing... but consumer crashes!
- Message is lost forever - payment was never processed.
This situation is recoverable with BLMOVE:
- Consumer crashes!
- Message is still in "processing" list, thus it can be recovered!
2.1.3.Timeout behavior
Timeout behavior
The timeout is the maximum time BLMOVE will wait. Once a message arrives, BLMOVE returns immediately, no matter how much time is left in the timeout period.
Example 1 (Source list is empty, timeout=5).
Redis blocks for 5 seconds, waiting for an element. After 5 seconds, returns nil (nothing available).
Example 2 (Source list is empty, timeout=0).
Redis blocks forever until an element is available.
Example 3 (Source list has elements).
Returns immediately ("order:123" (no waiting at all).).
Example 4 (Message arrives during timeout period).
- Starts blocking... waiting... and after 29 seconds, a message arrives.
- It returns immediately with the message (doesn't wait another 30 seconds!).
2.1.4.Example of Dedicated Worker Machines
Example of Dedicated Worker Machines
timeout=0 is perfect for containerized workers - single purpose
Why timeout=0 works well here?
- The only job for the worker is to process messages (no other responsibilities)
- Container/process manager handles lifecycle (Kubernetes sends
SIGTERM) - Most efficient - no unnecessary wake-ups
- Modern deployment pattern: stateless, disposable workers
- Failed messages will be left in
processingqueue (list).
2.2.Scenarios
Scenarios
Scenario 1 (Order Processing System).
Now if Consumer 2 crashes, order:1002 stays in processing:consumer2, recovery process can find it and reprocess.
Here LREM serves the purpose of ACK-ing the processed message.
Scenario 2 (Email Notification Queue).
2.3.Handling Failed Consumption with BRPOP
Handling Failed Consumption with BRPOP
When a task fails and remains in the processing list, we can reconsume it:
2.4.Dead Letter Queue (DLQ) Pattern
Dead Letter Queue (DLQ) Pattern
When a task fails multiple times, move it to a dead letter queue for manual review:
Complete example with retry logic:
2.5.Flow Diagram
Flow Diagram
3. Problems of BLMOVE
BLMOVEWhile BLMOVE provides reliability for message queues, it has several limitations that make it unsuitable for complex messaging scenarios:
3.1.The Problems
The Problems
3.1.1.No Native ACK Mechanism
No Native ACK Mechanism
Problem. Redis Lists don't have built-in acknowledgment support.
We must manually implement ACK using LREM, which creates additional complexity:
- Need to track processing state separately
- Manual retry logic required
- No automatic redelivery on consumer failure
Example of the manual work required:
Comparison with proper MQ systems:
3.1.2.No Consumer Group Support
No Consumer Group Support
Problem. Cannot distribute messages among multiple consumers efficiently.
With Lists, each message can only be consumed by one consumer, but there's no coordination:
Missing features:
- No automatic message distribution
- No consumer health tracking
- No rebalancing when consumers join/leave
- No pending message ownership tracking
- Cannot see which consumer is processing which message
What Kafka consumer groups provide:
3.1.3.Performance Degradation at Scale
Performance Degradation at Scale
Problem. Messages accumulate faster than consumers can process them.
When production rate exceeds consumption rate, the processing list grows indefinitely.
List also suffers from Time complexity issues:
| Operation | Complexity | Performance at Scale |
|---|---|---|
LPUSH | O(1) | Fast |
BLMOVE | O(1) | Fast |
LREM | O(N) | Slow when N is large! |
LRANGE | O(S+N) | Slow for large ranges |
3.1.4.Linear Structure Query Inefficiency
Linear Structure Query Inefficiency
Problem. Finding specific messages requires operations.
Lists are sequential data structures - no random access by ID:
Common queries that are inefficient:
What we need but Lists cannot provide:
- Query by message ID: lookup
- Query by timestamp: Range queries
- Query by field: Index-based search
- Query pending messages per consumer: Fast lookup
3.1.5.No Message Metadata
No Message Metadata
Problem. Cannot store additional information about messages.
Lists only store strings - no structured data:
3.2.Redis Stream
Redis Stream
These limitations led to Redis Streams, which solves all the problems above by providing:
- Built-in consumer groups
- Automatic ACK mechanism with
XACK - message lookup by ID
- Rich metadata support
- Pending message tracking (PEL, which stores consumed messages that has not been ACK-ed)
- Automatic consumer failover
- Range queries by timestamp
- Message claiming for recovery
4. When to Use BLMOVE vs Redis Streams
BLMOVE with Lists is suitable for:
- Low to medium throughput
- Simple message structure (string-based tasks)
- Single consumer or small number of consumers
- No need for message history or replay
- Learning Redis basics
Upgrade to Redis Streams when you need:
- High throughput
- Structured message data with multiple fields
- Consumer groups with automatic distribution
- Built-in ACK and pending message tracking
- Message history and replay capability
- Time-based queries and analytics
- Production-grade reliability
5. Next Steps
For production-ready message processing with consumer groups, automatic ACK, and all the features missing from BLMOVE, see the companion articles on Redis Stream:
- Redis Stream Part I: An Introduction to Redis Stream, as a Replacement of
BLMOVE - Redis Stream Part II: Production-Ready Message Queues with Consumer Groups
6. References
- 李健青, Redis 高手心法, Broadview
- Claude Sonnect 4.5





