Skip to content
XADD & XREAD — Redis Streams
step 1/3

Reading — step 1 of 3

Redis Streams

~2 min readScripting, Replication & Streams

XADD & XREAD — Redis Streams

Pub/Sub is fire-and-forget — if no one's listening, messages vanish. Lists work as queues but lose history once consumed. Streams (added in Redis 5) are the missing piece: an append-only log that persists every entry, supports multiple consumers, and remembers what each consumer has seen.

This is Redis answering "what would Kafka look like, embedded?"

Data Model

A stream is an ordered sequence of entries. Each entry has:

  • A monotonically increasing ID (<milliseconds>-<sequence>, e.g. 1700000000123-0)
  • A set of field/value pairs (like a hash)
events:  [ id=1-0  {action: signup, user: alice} ]
         [ id=2-0  {action: login,  user: alice} ]
         [ id=3-0  {action: signup, user: bob}   ]

The ID is the cursor — readers say "give me everything after 2-0" and they get the new entries.

Core Commands

Write side:

  • XADD <stream> <id> field value [field value ...] — append entry. <id> can be * (auto-generate based on current time + counter) or explicit (123-0). Returns the assigned ID.
  • XLEN <stream> — total entry count.

Read side:

  • XRANGE <stream> <start> <end> — historical slice. - = first, + = last. Returns all entries in range.
  • XREAD COUNT <n> STREAMS <stream> <last_id> — read entries newer than last_id. Returns up to n entries.
  • XREAD COUNT <n> BLOCK <ms> STREAMS <stream> $ — blocking read for new entries (the $ means "from the current end"). This is the pub/sub-like mode.

Consumer groups (advanced — not in this lesson):

  • XGROUP CREATE / XREADGROUP / XACK — multiple workers cooperatively process entries, like Kafka consumer groups.

ID Monotonicity

IDs must be strictly increasing. If you try XADD s 5-0 ... then XADD s 3-0 ..., you get:

-ERR The ID specified in XADD is equal or smaller than the target stream top item

This guarantee is what makes streams safe for replay: every consumer can rely on IDs as a strict total order.

Why Streams Beat Lists for Messaging

Lists (LPUSH/BRPOP)Streams
Message persistence after consumeLostRetained
Multiple consumers see same msgNo (one wins)Yes
Replay from arbitrary pointNoYes
Built-in IDsNoYes
Range queriesNoYes (XRANGE)
Consumer groupsNoYes (XREADGROUP)

Real-World Uses

  • Event sourcing — append every domain event, derive read models by replay
  • Activity feeds — Twitter-style timelines
  • Job queues with audit trail — even after a job runs, the history is queryable
  • CDC pipelines — capture changes from a primary store, downstream consumers replay

What You'll Build

XADD, XLEN, XRANGE, and a basic XREAD. Consumer groups are a follow-on you can layer on top once these primitives are in place.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…