Skip to content

Lists

A Redis List is an ordered collection of strings implemented as a doubly linked list. This gives you O(1) push and pop at both ends, making lists ideal for queues, stacks, and activity feeds. The trade-off: accessing an element in the middle is O(N), so lists are best used when you mostly work at the head or tail.

LPUSH key val [val ...] prepends one or more values to the head of the list. When you push multiple values at once, the last argument ends up at the head — each value is pushed individually from left to right.

RPUSH key val [val ...] appends one or more values to the tail.

127.0.0.1:6379> RPUSH tasks "buy milk"
(integer) 1
127.0.0.1:6379> RPUSH tasks "write code" "review PR"
(integer) 3
127.0.0.1:6379> LPUSH tasks "urgent: fix bug"
(integer) 4
RPUSH tasks "buy milk"
RPUSH tasks "write code" "review PR"
LPUSH tasks "urgent: fix bug"
LRANGE tasks 0 -1
LLEN tasks
LINDEX tasks 0
LINDEX tasks -1

Once you have a list, these three commands cover most read patterns:

  • LRANGE key start stop — returns elements from index start to stop (inclusive, 0-based). Use -1 for the last element, -2 for second-to-last, and so on.
  • LLEN key — returns the number of elements in the list.
  • LINDEX key index — returns the single element at the given index. Negative indices count from the tail.
127.0.0.1:6379> LRANGE tasks 0 -1
1) "urgent: fix bug"
2) "buy milk"
3) "write code"
4) "review PR"
127.0.0.1:6379> LLEN tasks
(integer) 4
127.0.0.1:6379> LINDEX tasks 0
"urgent: fix bug"
127.0.0.1:6379> LINDEX tasks -1
"review PR"

LRANGE tasks 0 -1 is the idiomatic way to fetch every element in a list. LINDEX is O(N) — it traverses from the nearest end — so prefer it only for the first or last few positions.

LSET key index value overwrites the element at a specific index. The list must already contain an element at that position, otherwise Redis returns an error.

LREM key count value removes occurrences of value:

  • count > 0 — remove up to count occurrences scanning from head to tail
  • count < 0 — remove up to |count| occurrences scanning from tail to head
  • count = 0 — remove all occurrences
127.0.0.1:6379> LSET tasks 1 "buy oat milk"
OK
127.0.0.1:6379> LRANGE tasks 0 -1
1) "urgent: fix bug"
2) "buy oat milk"
3) "write code"
4) "review PR"
127.0.0.1:6379> RPUSH tasks "write code"
(integer) 5
127.0.0.1:6379> LREM tasks 0 "write code"
(integer) 2
RPUSH tasks "buy milk"
RPUSH tasks "write code" "review PR"
LPUSH tasks "urgent: fix bug"
LSET tasks 1 "buy oat milk"
LRANGE tasks 0 -1
RPUSH tasks "write code"
LREM tasks 0 "write code"
LRANGE tasks 0 -1

LTRIM key start stop modifies the list in place, retaining only the elements in [start, stop] and discarding everything outside that range. It returns OK immediately, making it safe to call after every write.

127.0.0.1:6379> DEL recent
(integer) 1
127.0.0.1:6379> RPUSH recent "page-A" "page-B" "page-C" "page-D" "page-E"
(integer) 5
127.0.0.1:6379> LTRIM recent 0 2
OK
127.0.0.1:6379> LRANGE recent 0 -1
1) "page-A"
2) "page-B"
3) "page-C"
DEL recent
RPUSH recent "page-A" "page-B" "page-C" "page-D" "page-E"
LRANGE recent 0 -1
LTRIM recent 0 2
LRANGE recent 0 -1
What does `LRANGE tasks 0 -1` return?
Which push command adds an element to the HEAD of a list?
What does `LREM key 0 val` do?
After `LTRIM mylist 0 2`, how many elements remain?