Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Redis lists are ordered collections that you can read, update, trim, and consume from either end. That makes one data type suitable for a stack, a first-in-first-out queue, a bounded activity log, or a hand-off queue between producers and workers. The essential pattern is simple: use LPUSH or RPUSH to add items, LPOP or RPOP to remove them, LRANGE to inspect them without removal, and BLPOP or BRPOP when a consumer should wait for work.

This guide explains the command families, their index rules and complexity, practical list designs, blocking behavior, trimming, moving items between lists, and the version checks to make before using newer commands.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How Redis lists work

A Redis list is an ordered sequence stored under one key. Each element is a value, commonly a string containing a job identifier, JSON document, event, or message. Redis exposes both ends of the sequence as the head (left) and tail (right).

Because insertion and removal are defined relative to an end, the same key can implement different data structures:

  • Stack: push and pop on the same end, such as LPUSH followed by LPOP.
  • Queue: append on one end and consume from the other, such as RPUSH followed by LPOP.
  • Double-ended queue: choose either end for each operation.
  • Work queue: producers push jobs and workers pop them, optionally waiting with a blocking pop.

List positions are zero-based. Index 0 is the first element from the left, while negative indexes count backward from the right: -1 is the last element, -2 is the item before it, and so on.

Add elements with LPUSH and RPUSH

LPUSH: insert at the head

LPUSH key element [element ...] inserts one or more values at the left side of a list. If the key does not exist, Redis creates the list.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
LPUSH notifications "backup finished"
LPUSH notifications "deployment started"

After these commands, deployment started is at the head and backup finished follows it. When several elements are supplied in one command, Redis inserts them from left to right in the command’s argument order, so the last supplied element becomes the new head.

RPUSH: append at the tail

RPUSH key element [element ...] appends values at the right side and also creates the key when it does not exist.

RPUSH jobs "resize-image-101" "resize-image-102" "resize-image-103"

For a conventional FIFO queue, producers generally use RPUSH and consumers use LPOP. For a LIFO stack, use the same end for both operations, for example LPUSH and LPOP.

Choosing a push direction

Producer command Consumer command Behavior Typical use
LPUSH LPOP Last pushed item is removed first Stack (LIFO)
RPUSH RPOP Last appended item is removed first Stack (LIFO)
RPUSH LPOP First appended item is removed first Queue (FIFO)
LPUSH RPOP First pushed item is removed first Queue (FIFO)

Pick one convention per key and document it. Mixing directions accidentally is a common source of reversed job order.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Remove elements with LPOP and RPOP

LPOP: remove from the head

LPOP key removes and returns the leftmost element. It is the normal consumer operation for a queue populated with RPUSH.

LPOP jobs

If the list has no element available, the non-blocking command returns a null result. A client that should wait rather than poll repeatedly should use BLPOP.

RPOP: remove from the tail

RPOP key removes and returns the rightmost element.

RPOP jobs

Use RPOP with LPUSH for FIFO behavior, or pair it with RPUSH when you intentionally want LIFO behavior from the right.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Non-blocking versus blocking removal

LPOP and RPOP return immediately. They are appropriate when the application can handle an empty result or has another scheduling mechanism. Blocking pops suspend the connection until a list receives an item or the timeout expires; the blocking behavior is covered later.

Read list contents without removing them

LRANGE: return a range

LRANGE key start stop reads a slice while leaving the list unchanged. Both indexes are inclusive.

LRANGE jobs 0 -1

The range 0 -1 returns the entire list. To read only the first ten entries, use LRANGE jobs 0 9. Negative indexes are useful for recent entries, such as LRANGE jobs -10 -1.

The command’s complexity is O(S+N), where S is the distance of the start offset from the nearer end and N is the number of elements returned. Small ranges near either end are therefore cheaper than repeatedly requesting large, distant slices.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

LLEN: get the number of elements

LLEN key returns the list length in O(1) time.

LLEN jobs

Use it for queue-depth metrics, capacity checks, or deciding whether a batch is ready. A missing key behaves as an empty list for length purposes.

Inspecting a list safely

For diagnostics, start with LLEN, then request a bounded range rather than an unbounded list. For example:

LLEN notifications
LRANGE notifications 0 49

This gives the total count and at most 50 values without removing anything.

Access or replace one position with LINDEX and LSET

LINDEX: read one element

LINDEX key index returns the value at a specific position without changing the list.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
LINDEX jobs 0
LINDEX jobs -1

The first command reads the head and the second reads the tail. LINDEX is O(N) in the general case, although the first and last elements are O(1). Random access in the middle of a large list is consequently a poor substitute for a separate key-based lookup.

LSET: replace one element

LSET key index element replaces the value at an existing index.

LSET jobs 2 "resize-image-102-retried"

LSET has the same complexity profile as LINDEX: O(N) generally and O(1) at the first or last position. It fails if the key does not contain a list or if the index is outside the current range.

Find values with LPOS

LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len] searches for matching values and returns their positions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
LPOS jobs "resize-image-102"
LPOS jobs "retry" RANK 2 COUNT 3 MAXLEN 1000

The optional arguments let you select a later match with RANK, request multiple positions with COUNT, and cap how far Redis scans with MAXLEN. Use a bounded MAXLEN when a list can grow very large and a complete scan is unnecessary.

Search compares list values, not fields inside a JSON string. If you need to query many attributes, a list alone is usually the wrong index; store searchable metadata separately and keep the list for ordering.

Remove matching values with LREM

LREM removes occurrences of a value from a list. Its count argument controls the direction and number of removals:

LREM jobs 1 "resize-image-102"
LREM jobs -1 "resize-image-102"
LREM jobs 0 "resize-image-102"
  • A positive count removes up to that many matches from the head toward the tail.
  • A negative count removes up to the absolute value from the tail toward the head.
  • A count of zero removes every matching element.

When the final element is removed, Redis deletes the list key. That matters for code that checks key existence as a signal that a queue or log still has data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep a bounded list with LTRIM

LTRIM key start stop keeps only the specified inclusive range and removes everything outside it. Negative indexes count from the tail, with -1 representing the last element.

LTRIM recent-events 0 999

The command above retains the first 1,000 entries. To retain the newest 1,000 entries after appending at the tail, use:

LTRIM recent-events -1000 -1

LTRIM is O(N), where N is the number of elements removed. A common bounded-log pattern is:

RPUSH recent-events "$event"
LTRIM recent-events -1000 -1

This keeps the list from growing without limit. If strict ordering and trimming must be coordinated with other writes, issue the related commands in a transaction or through a server-side atomic mechanism appropriate to your client; the two commands otherwise execute as separate requests.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Move an item between lists with LMOVE

LMOVE source destination <LEFT | RIGHT> <LEFT | RIGHT> removes an item from one end of the source list and pushes it onto one end of the destination list.

LMOVE pending processing LEFT RIGHT

This removes the head of pending and appends it to the tail of processing. The four useful direction combinations are:

Source side Destination side Effect
LEFT LEFT Move the source head to the destination head
LEFT RIGHT Move the source head to the destination tail
RIGHT LEFT Move the source tail to the destination head
RIGHT RIGHT Move the source tail to the destination tail

The lists documentation and the LMOVE command page identify LMOVE as introduced in Redis 6.2.0. Another version reference lists 1.0.0, so verify the command against the documentation for the exact server release you operate before depending on it in production.

The lists documentation also describes LMOVEM as an 8.10.0 command. It is therefore a recent-server feature; do not assume it exists on Redis 7.x or earlier installations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for work with BLPOP and BRPOP

BLPOP syntax and key order

BLPOP key [key ...] timeout removes and returns an element from the first non-empty list among the keys supplied. Redis checks the keys in the order given.

BLPOP high-priority normal-priority 30

In this example, Redis checks high-priority first and uses normal-priority only when the first list is empty. The returned result identifies the key and the value, allowing one consumer loop to serve multiple queues.

Timeout behavior

The timeout is expressed in seconds. A timeout of 0 waits indefinitely until another client pushes an element. A positive timeout waits up to that many seconds and then returns an empty result if no item arrives.

BLPOP jobs 0

Blocking applies to the connection, not just one application thread. Use a dedicated connection for a blocking consumer so ordinary commands such as health checks, acknowledgements, or metrics are not held behind the wait.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

BRPOP

BRPOP is the right-end counterpart to BLPOP. It blocks while waiting and removes from the tail. Choose it when your producer direction and queue semantics require right-end consumption.

When to use blocking pops

  • Use blocking pops when workers should sleep without polling while the queue is empty.
  • Use a finite timeout when the worker needs periodic shutdown checks, lease renewal, or metrics updates.
  • Use timeout 0 only when an indefinitely waiting connection is intentional and your shutdown procedure can close it cleanly.
  • Keep key priority explicit: the first non-empty key in the command is selected.

Common list designs

FIFO job queue

  1. Producer: RPUSH jobs job-id.
  2. Worker: BLPOP jobs 30.
  3. Worker processes the returned value and records success or failure in a separate system.
  4. Worker repeats the blocking pop until shutdown.

This design preserves insertion order for a single queue. It does not by itself provide retries, visibility timeouts, acknowledgements, or dead-letter handling; those behaviors require additional application logic and keys.

LIFO work stack

  1. Push new work with LPUSH work item.
  2. Take the newest item with LPOP work.

LIFO can reduce latency for recently created tasks, but older tasks can remain behind a continuous stream of new pushes.

Bounded recent-event log

  1. Append each event with RPUSH recent-events event.
  2. Immediately retain the desired window with LTRIM recent-events -1000 -1.
  3. Read a page with LRANGE recent-events 0 49.

The trim limit is a count of retained elements, not a time period. Events may represent different time spans depending on traffic volume.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Staging and processing lists

Use LMOVE staging processing LEFT RIGHT to transfer one item between lists while selecting both ends explicitly. This is useful when an application maintains separate pending and in-progress lists, but moving an item is not the same as durable acknowledgement: a worker failure after the move can still require recovery logic.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Complexity and performance choices

Command Primary job Complexity stated in Redis references Practical implication
LPUSH, RPUSH Add at an end Designed for end operations Use for queue or stack ingestion
LPOP, RPOP Remove at an end Designed for end operations Efficient consumers
LLEN Count elements O(1) Safe for frequent depth checks
LRANGE Read a range O(S+N) Keep ranges bounded; S is distance to the nearer end and N is returned count
LINDEX Read one index O(N), O(1) at first or last Avoid repeated middle-index scans
LSET Replace one index O(N), O(1) at first or last Prefer end updates or another structure for random writes
LTRIM Discard outside a range O(N) for elements removed Trim in bounded-log workflows

The complexity of an individual command is not the whole cost of a design. Returning thousands of values also consumes network bandwidth and client memory, and repeatedly scanning a large list can dominate a workload even when each command is valid.

Index, range, and trimming pitfalls

  • Forgetting that LRANGE stop is inclusive: LRANGE key 0 9 returns ten positions, not nine.
  • Misreading negative indexes: -1 is the last element, while -1000 means the thousandth from the right and may be outside a short list.
  • Using LINDEX for random records: middle access is O(N); store an item under its own key when direct lookup is the real requirement.
  • Trimming the wrong side: LTRIM key 0 999 keeps the oldest side when new entries are appended at the tail; LTRIM key -1000 -1 keeps the newest 1,000.
  • Assuming an empty range is harmless: a range that excludes every element can remove the list when used with LTRIM. Validate calculated boundaries in application code.

Version checks before deployment

The Redis command index provides selectors for Redis 8.10, 8.4, 8.0, 7.4, 7.2, and 6.2. Select the server version in the official command reference before relying on optional arguments or newer commands.

In particular:

  • LMOVE is documented by the lists and LMOVE pages as a Redis 6.2.0 addition, although another reference lists 1.0.0. Treat 6.2.0 as the better-supported introduction and verify your deployment.
  • LMOVEM is described as available in Redis 8.10.0, so it should be treated as unavailable on older servers unless your own versioned documentation says otherwise.
  • The exact option set for pop commands can vary by server release. Check the command page for your installed version rather than copying options from a newer example.

To identify the server release from a Redis client, inspect the server information exposed by your client or run the appropriate INFO command in an administrative context. Test the complete command sequence against the same major and minor version used in production.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting checklist

The command reports a wrong type

A key can hold only one Redis data type at a time. If a key currently contains a string, hash, set, or another type, list commands fail with a wrong-type error. Inspect the key type before changing application code, and use a distinct key name when migrating data.

The queue appears empty

  • Run LLEN queue-name to distinguish an empty list from a consumer that is reading another key.
  • Confirm producer and consumer use the intended ends; RPUSH plus RPOP is a stack, not FIFO.
  • Check that a prior consumer has not already removed the item.
  • For a blocking consumer, verify the timeout and that the connection remains open.

BLPOP never returns

A timeout of 0 is intentionally indefinite. Use a positive timeout while diagnosing shutdown and network behavior, and ensure another client pushes to one of the keys in the command. Remember that keys are checked in the order supplied.

Items disappear unexpectedly

Review every command that removes data: LPOP, RPOP, blocking pops, LMOVE, LREM, and LTRIM. Log the key, direction, index range, and consumer identity around destructive operations. An LREM count of zero removes all matching values, not just one.

List growth causes memory pressure

Measure length with LLEN, identify producers that never trim, and set an explicit retention policy. For a fixed number of recent entries, append at the tail and trim with a negative range. If retention is time-based or requires durable replay and acknowledgements, a list may not be sufficient by itself.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redis list command cheat sheet

Goal Command form
Push at head LPUSH key element [element ...]
Push at tail RPUSH key element [element ...]
Pop at head LPOP key
Pop at tail RPOP key
Read a range LRANGE key start stop
Count elements LLEN key
Read an index LINDEX key index
Replace an index LSET key index element
Find positions LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len]
Remove matching values LREM key count element
Keep a range LTRIM key start stop
Move across lists LMOVE source destination LEFT|RIGHT LEFT|RIGHT
Block on the first available list BLPOP key [key ...] timeout
Block from the right BRPOP key [key ...] timeout

Start by deciding which end producers and consumers use. Then choose non-blocking or blocking removal, bound reads and retention where appropriate, and verify newer commands against the Redis version actually running in each environment.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.