Redis 📂 Messaging and real-time · 1 of 2 19 min read

Redis Pub/Sub vs Streams — Real-Time Messaging and When to Use Each

A practical Redis messaging tutorial. Learn Pub/Sub to broadcast messages to many clients with SUBSCRIBE, PUBLISH and PSUBSCRIBE patterns, why Pub/Sub is fire-and-forget, and how streams differ by storing messages so offline readers can catch up. Includes animated diagrams and a clear when-to-use guide.

Section 01

Two Ways to Move Messages

A Radio Station and a Voice Recorder
A radio station broadcasts live. Everyone who has the radio on right now hears the song. If your radio is off, you miss it — there is no rewind. That is Redis Pub/Sub.

A voice recorder saves everything. You can play it back later, from any point, as many times as you like. That is a Redis stream.

Both send messages to listeners. The difference is memory: Pub/Sub forgets the instant it sends; a stream remembers. This tutorial shows how each works and how to pick.

Section 02

Pub/Sub — Broadcast to Many Clients

Pub/Sub (publish / subscribe) sends a message to every client listening on a channel, at the same moment. A publisher sends with PUBLISH. Listeners join a channel with SUBSCRIBE. One message reaches all of them — a fan-out.

One PUBLISH to a channel is delivered to every current subscriber at once. The reply tells you how many received it.

📢 One Message, Many Listeners
Publisher PUBLISH news channel: news subscriber A ✅ subscriber B ✅ subscriber C ✅ PUBLISH news "hello" → (integer) 3 (three subscribers received it)
# terminal 1: listen on a channel (this connection now waits for messages)
SUBSCRIBE news

# terminal 2: send a message to that channel
PUBLISH news "market opens at 9am"
# -> (integer) 3   the number of subscribers that got it
what subscriber A sees
1) "message" 2) "news" 3) "market opens at 9am"
⚠️
A SUBSCRIBE Connection Is Busy

Once a connection runs SUBSCRIBE, it can only handle messages — it cannot run normal commands like GET. Use a separate, dedicated connection for subscribing, and keep your normal commands on another connection.


Section 03

Pattern Subscribe — One Rule, Many Channels

You do not have to name every channel. PSUBSCRIBE uses a pattern, so one subscriber can catch many related channels at once. A rule like order.* matches order.created, order.paid, and order.shipped.

A pattern subscriber receives from every channel that matches. Channels that do not match are ignored.

🔍 PSUBSCRIBE Matches a Family of Channels
order.created order.paid order.shipped user.login ✗ no match pattern match PSUBSCRIBE order.* worker gets all order.* events
# subscribe to every channel that starts with "order."
PSUBSCRIBE order.*

# any of these now reach the subscriber
PUBLISH order.created "#9001"
PUBLISH order.paid    "#9001"

# this one does NOT match order.* so it is not delivered
PUBLISH user.login    "user 57"
CommandWhat it does
SUBSCRIBE chListen on one or more channels
PUBLISH ch msgSend a message; returns how many got it
PSUBSCRIBE patternListen on all channels matching a pattern
UNSUBSCRIBE / PUNSUBSCRIBEStop listening

Section 04

The Catch — Pub/Sub Is Fire-and-Forget

Pub/Sub is fast and simple, but it has no memory. A message is sent to whoever is listening at that instant, and then it is gone. Know these three limits before you rely on it.

📴
Offline means missed
no catch-up
A subscriber that is disconnected when you publish never gets the message. There is no way to ask for what it missed.
🗑️
No history
nothing stored
Messages are not saved. You cannot replay them, count them later, or read the last ten. Once sent, they are gone.
🏇
At most once
no ack
There is no acknowledgement. If a subscriber crashes mid-message, no one retries. Delivery is best-effort only.
🧠
That Is Fine for Live-Only Signals

Fire-and-forget is perfect when only "right now" matters: a typing indicator, a live score, a "someone just joined" ping, or telling all your app servers to clear a cache. If missing a message is harmless, Pub/Sub is the simplest tool.


Section 05

Streams vs Pub/Sub — The Key Difference

A stream is an append-only log. Every message is stored with an ID, so a reader can come back later and read from where it left off. This one difference — memory — decides most choices between the two.

Left: Pub/Sub delivers live; an offline listener misses the message forever. Right: a stream stores it, so a reader that was offline catches up when it returns.

⚖️ Fire-and-Forget vs Stored-and-Replayable
Pub/Sub — fire-and-forget PUBLISH news online ✅ offline ✗ the offline client missed it forever — no way to get it back Stream — stored, can replay XADD events * events (stored) 1760-0 1761-0 1762-0 1763-0 reader back onlineXREAD from last ID it reads every event it missed — nothing is lost
📢 Pub/Sub
Live delivery only
Offline listeners miss it
No history, no replay
No acknowledgement
Simplest to set up
📜 Stream
Stored with IDs
Late readers catch up
Replay any time
Consumer groups + XACK
A bit more to manage
PointPub/SubStream
Stores messages?NoYes
Offline reader catches up?NoYes
Replay old messages?NoYes
Delivery guaranteeAt most onceAt least once (with XACK)
Share work across workersAll get every messageConsumer groups split it
Memory useTiny (nothing kept)Grows — cap with MAXLEN
Setup effortLowestA little more

Section 06

Which One Should You Pick?

📢
Pick Pub/Sub when
Only "right now" matters and a missed message is harmless. Typing indicators, live scores, presence pings, telling all servers to clear a cache.
SUBSCRIBE, PUBLISH
📜
Pick a Stream when
Every message must be handled, even by a reader that was offline. Orders, payments, jobs, audit logs, anything you may replay.
XADD, XREAD, XACK
🤝
Use both when
A stream is the safe record of events, and Pub/Sub pushes a quick "something changed" ping so live clients react instantly.
stream + a live ping
💡
A Simple Rule of Thumb

Ask one question: "If a listener is offline for a second, is it OK to miss this message?" If yes, use Pub/Sub. If no, use a stream. When in doubt, a stream is the safer choice because it keeps the message.


Section 07

Golden Rules

📢 Pub/Sub & Streams — Non-Negotiable Rules
1
Pub/Sub has no memory. It delivers to whoever is listening now and forgets. An offline subscriber misses the message for good.
2
Use a dedicated connection to subscribe. A SUBSCRIBE connection can only receive messages, not run normal commands. Keep the two apart.
3
Use PSUBSCRIBE for families of channels. One pattern like order.* catches many related channels without naming each one.
4
Choose a stream when messages must not be lost. Streams store every event, so late or crashed readers can catch up and replay.
5
Ask the offline question. "Is it OK to miss this if I am offline for a second?" Yes → Pub/Sub. No → stream. In doubt, pick the stream.
6
Combine them for real-time apps. Store the event in a stream for safety, and fire a Pub/Sub ping so live clients react at once.