← index

Redis Streams: entries, groups, and the PEL

Modelled on src/t_stream.c, Redis 7.2.14. Every line number cited on this page is from that file.

Three things on this page are the ones people get wrong. XDEL and XTRIM never touch a consumer group, so a pending entry outlives the entry it points at (t_stream.c:3530, t_stream.c:719 — neither function mentions cgroups); the orphans below stay until XACK or XAUTOCLAIM removes them. A deleted entry is not removed, it is flagged and left in the listpack, still holding its slot against stream-node-max-entries (t_stream.c:1286, t_stream.c:542). And ~ does not trim to your number: it removes whole radix-tree nodes and stops at the first node it cannot remove whole (t_stream.c:773), bounded again by LIMIT (t_stream.c:742).

mystream

XLEN returns s->length, t_stream.c:2175

Radix tree → listpack nodes

t_stream.c:497 master entry · :641 delta IDs

The radix key is the ID of the first entry inserted into the node. The master entry is a standalone header — count, deleted, then the field names — and is not itself a stream entry (t_stream.c:502). Each entry stores its ID as a delta against that key.

Consumer groups

group PEL and consumer PEL share one NACK, stream.h:64

Reply log

XADD

t_stream.c:2010

XTRIM

t_stream.c:3612

XGROUP CREATE

t_stream.c:2587

XREADGROUP

t_stream.c:2186

XACK

t_stream.c:2833

Group-scoped: no consumer argument. The NACK itself names the consumer whose PEL is also cleared (t_stream.c:2868).

XAUTOCLAIM

t_stream.c:3351

Config

config.c:3228, :3243

Real defaults are 100 and 4096. Small values here so a node fills in a few clicks; byte sizes are simulated from field and value lengths.