A Redis Stream is an append-only log data structure that supports consumer groups, message IDs, and acknowledgments. Each entry carries an ID composed of the millisecond timestamp at which it was created plus a sequence number for entries written within the same millisecond, ensuring total ordering. Entries are added with XADD and read with XREAD. To coordinate multiple workers, XREADGROUP lets clients consume a stream as part of a consumer group so that each entry is delivered to exactly one consumer. Once a consumer has successfully processed an entry, XACK acknowledges it; unacknowledged entries remain in the pending entries list and can be inspected or claimed later.
Streams are designed for durability and replayability, which is the main problem they solve relative to Pub/Sub and Lists. Lists can serve as queues but lack a built-in notion of acknowledgment or per-consumer delivery, and Pub/Sub is fire-and-forget: messages are not stored and are simply dropped if no subscriber is listening. Streams preserve history and let new consumers pick up where they left off. To keep a stream from growing without bound, XADD accepts a MAXLEN ~ N option that performs approximate trimming to roughly N of the most recent entries with very low overhead, avoiding the cost of an exact size check on every write.
Redis Pub/Sub is a simpler real-time messaging model in which publishers send messages to channels and subscribers receive them as they arrive. SUBSCRIBE attaches a client to one or more channels, while PSUBSCRIBE matches channels by a glob pattern, so a single subscriber can receive traffic from many related channels. The defining limitation of Pub/Sub compared to Streams is its fire-and-forget semantics: there is no storage of messages, no acknowledgments, and no replay; if no subscriber is connected when a message is published, the message is lost.