Redis Lists
A Redis List stores a sequence of strings in the order you add them. You can add items to the front or back of the list, read items by position, and remove items from either end. Lists work well for queues, recent activity feeds, and task pipelines.
The Train Carriage Analogy
Picture a train with numbered carriages. New carriages can attach to the front or the back. You can look at any carriage by its position number, and you can detach carriages from either end. The order of carriages is always preserved.
A Redis List (key: "tasks")
HEAD (left/front) TAIL (right/back)
│ │
▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ "send │ │ "resize │ │ "update │ │ "email │
│ invoice│ │ image" │ │ DB" │ │ user" │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
index [0] index [1] index [2] index [3]
LPUSH adds to the HEAD (left)
RPUSH adds to the TAIL (right)
LPOP removes from the HEAD
RPOP removes from the TAIL
Adding Items with LPUSH and RPUSH
127.0.0.1:6379> RPUSH tasks "send invoice" (integer) 1 127.0.0.1:6379> RPUSH tasks "resize image" (integer) 2 127.0.0.1:6379> RPUSH tasks "update DB" (integer) 3 List is now: ["send invoice", "resize image", "update DB"] 127.0.0.1:6379> LPUSH tasks "URGENT: fix bug" (integer) 4 List is now: ["URGENT: fix bug", "send invoice", "resize image", "update DB"]
Reading Items
LRANGE – Read a Slice of the List
127.0.0.1:6379> LRANGE tasks 0 -1 1) "URGENT: fix bug" 2) "send invoice" 3) "resize image" 4) "update DB" 0 to -1 means "from index 0 to the last item." 127.0.0.1:6379> LRANGE tasks 0 1 1) "URGENT: fix bug" 2) "send invoice"
LINDEX – Read One Item by Position
127.0.0.1:6379> LINDEX tasks 2 "resize image"
LLEN – Count Items in the List
127.0.0.1:6379> LLEN tasks (integer) 4
Removing Items with LPOP and RPOP
127.0.0.1:6379> LPOP tasks "URGENT: fix bug" ← removed from front 127.0.0.1:6379> RPOP tasks "update DB" ← removed from back List now: ["send invoice", "resize image"]
Building a Task Queue with Lists
A queue follows a First-In, First-Out rule — the first task added is the first task processed. Redis makes this trivial: producers push to the right (RPUSH), workers pop from the left (LPOP).
Producer (your web app) Consumer (background worker)
│ │
│ RPUSH queue "job-A" │
│ RPUSH queue "job-B" │
│ RPUSH queue "job-C" │
│ │
│ LPOP queue → "job-A" (process)
│ LPOP queue → "job-B" (process)
│ LPOP queue → "job-C" (process)
Queue state over time:
After 3 pushes: [job-A, job-B, job-C]
After 1st pop: [job-B, job-C]
After 2nd pop: [job-C]
After 3rd pop: []
BRPOP – Blocking Pop (Wait for an Item)
A worker that calls LPOP on an empty list gets nil immediately and must loop and check again. BRPOP blocks the connection and waits for a new item — no wasted looping.
127.0.0.1:6379> BRPOP queue 30 (waiting up to 30 seconds for an item...) Once a producer pushes something: 1) "queue" 2) "job-D"
Recent Activity Feed Example
Goal: Keep the 5 most recent actions by user 1001. LPUSH user:1001:activity "viewed product 88" LPUSH user:1001:activity "added to cart" LPUSH user:1001:activity "applied coupon" LPUSH user:1001:activity "removed item" LPUSH user:1001:activity "checked out" LTRIM user:1001:activity 0 4 ← keep only the first 5 LRANGE user:1001:activity 0 -1 1) "checked out" 2) "removed item" 3) "applied coupon" 4) "added to cart" 5) "viewed product 88"
Key Points
- Redis Lists maintain insertion order and support access from both ends.
- RPUSH adds to the tail; LPUSH adds to the head. RPOP and LPOP remove from each end.
- LRANGE reads a portion of the list without removing items.
- Use RPUSH + LPOP as a simple, reliable task queue.
- BRPOP blocks the connection until an item appears — ideal for workers that wait for jobs.
- LTRIM keeps only a fixed-size window of items, which controls memory usage.
