What Is Redis Pub/Sub?
Redis Pub/Sub is a messaging pattern in which publishers send messages to named channels, and every client currently subscribed to that channel receives a copy. Publishers do not know who is listening, and subscribers do not know who is publishing — the channel name is the only contract between them.
(The feature is written pub/sub, pubsub and pub sub more or less interchangeably. They all refer to the same thing: Redis's SUBSCRIBE and PUBLISH commands.)
One property defines everything else about it: Redis stores nothing. A message is delivered to whoever is connected at that instant and is then gone — no persistence, no replay, no acknowledgment. That makes pub/sub extremely fast and extremely simple, and it is also the single thing people most often get wrong about it. If a message matters, read the section on what pub/sub does not do before you build on it.
How Redis Pub/Sub Works
Three commands cover the whole model:
SUBSCRIBE news.sport
PUBLISH news.sport "Final score 2-1"
UNSUBSCRIBE news.sport
Channels are never declared or created. A channel exists exactly as long as someone is subscribed to it; publishing to a name nobody is listening on is a valid, successful, entirely pointless operation. That is why PUBLISH returns an integer — the number of clients the message reached:
PUBLISH news.sport "Final score 2-1"
(integer) 3
Do not trust that number in a cluster. The documentation is explicit: "in a Redis Cluster, only clients that are connected to the same node as the publishing client are included in the count." A return of 0 on a clustered deployment does not mean nobody received the message — it means nobody on that particular node did. Any "did anyone get it?" logic built on the return value is quietly broken the moment you move to Cluster.
Two smaller surprises. Subscribers receive messages "in the order that the messages are published", so ordering from a single publisher is guaranteed. And pub/sub ignores database numbers entirely — the docs note that "publishing on db 10, will be heard by a subscriber on db 1." There is no SELECT isolation, so if you need scoping, prefix the channel names yourself.
Pattern Subscriptions With PSUBSCRIBE
PSUBSCRIBE subscribes to a glob-style pattern rather than an exact name, so one subscription can cover a whole namespace:
PSUBSCRIBE news.*
PSUBSCRIBE h?llo
PSUBSCRIBE h[ae]llo
news.* matches news.art.figurative and news.music.jazz; h?llo matches hello and hallo but not heello; h[ae]llo matches only hello and hallo. Use \ to match a special character literally.
Pattern messages arrive in a different shape — a four-element pmessage carrying the matched pattern, the originating channel and the payload, where an ordinary message has three. And a client subscribed to both a channel and a pattern that matches it receives the message twice: once as message, once as pmessage. Subscribing to foo and f* together is a duplicate-delivery bug waiting to happen.
Patterns Are Billed to the Publisher, Not the Subscriber
The cost model here is not the one most people assume. PUBLISH is documented as O(N+M) — "where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client)."
Read that M term carefully. It is server-global and match-independent: every publish on every channel is evaluated against every pattern registered on that node, whether or not any of them match. One client that registers 5,000 patterns imposes 5,000 glob evaluations on every message every other client publishes. Patterns are not a subscriber-side convenience with a small local cost — they are a tax on the whole node, paid by publishers.
Use exact channel names where you can, and treat a large pattern count as a capacity problem rather than a style choice.
What Redis Pub/Sub Does Not Do
The official wording leaves no room for interpretation:
"Redis' Pub/Sub exhibits at-most-once message delivery semantics. As the name suggests, it means that a message will be delivered once if at all. Once the message is sent by the Redis server, there's no chance of it being sent again. If the subscriber is unable to handle the message (for example, due to an error or a network disconnect) the message is forever lost."
Concretely, there is no persistence, no replay, no acknowledgment, no backlog and no consumer groups. Messages published while a subscriber is disconnected are not queued for it — they were delivered to whoever was connected at the time, and that is the end of it. Valkey's documentation states it flatly — "Pubsub channels are not persisted" — and spells out the case people forget: if nobody is subscribed at the moment of publication, the message is simply lost.
Why Your Subscriber Got Disconnected
There is a second, less obvious way to lose messages, and it causes real incidents. Redis caps the output buffer it will hold for a subscriber:
client-output-buffer-limit pubsub 32mb 8mb 60
A subscriber whose output buffer reaches the hard limit of 32 MB is disconnected immediately. One that stays above the soft limit of 8 MB for 60 continuous seconds is also disconnected. As the client-handling docs put it: "When the limit is reached the client connection is closed and the event logged in the Redis log file."
The important word is disconnected, not throttled. There is no back-pressure in Redis Pub/Sub. A publisher never slows down for a struggling subscriber and never learns that one exists. A consumer that falls behind is dropped, and because there is no replay, everything it missed is gone permanently. A slow consumer on a queue causes a backlog; a slow consumer on pub/sub causes silent data loss.
If any of this is unacceptable for your use case, the answer is Redis Streams, which persist entries, track per-consumer acknowledgment and support replay from any point.
Pub/Sub vs. Streams vs. Lists
| Pub/Sub | List | Stream | |
|---|---|---|---|
| Consumer offline | Message lost | Message waits | Message waits |
| Replay | No | No — popping removes | Yes, by ID or timestamp |
| Acknowledgment | None | None | Per message, server-side |
| Many readers, same message | Yes — all subscribers | No — first taker wins | Either, depending on group |
| Slow consumer | Disconnected, messages lost | Backlog grows | Backlog grows |
| Memory | Nothing retained | Shrinks as consumed | Grows until trimmed |
Pub/Sub is the right tool when messages are only interesting the instant they happen and a missed one costs nothing — live dashboards, cache-invalidation signals, presence updates, chat fan-out to connected clients. It is the wrong tool for work queues, financial events or anything where "the subscriber was restarting" is not an acceptable reason to lose data. For that comparison in depth, see Redis Streams and Redis queues.
Sharded Pub/Sub in Redis Cluster
Ordinary pub/sub has a scaling problem in Redis Cluster, and the cluster specification is blunter about it than the pub/sub page is: "The clients can send SUBSCRIBE to any node and can also send PUBLISH to any node. It will simply broadcast each published message to all other nodes."
That is not routing. It is unconditional fan-out with no knowledge of where subscribers actually are. On a 20-node cluster, a message published for a single subscriber still crosses 19 cluster-bus links. Add nodes to handle more throughput and every publish gets more expensive — pub/sub scales in exactly the wrong direction.
Redis 7.0 introduced sharded pub/sub to fix this. Shard channels are hashed to slots using the same CRC16(key) mod 16384 algorithm that maps keys, and messages propagate only to the nodes serving that slot — the primary and its replicas:
SSUBSCRIBE orders.eu
SPUBLISH orders.eu "order 4711 shipped"
SUNSUBSCRIBE orders.eu
In the docs' words, this "restricts the propagation of messages to be within the shard of a cluster… This allows users to horizontally scale the Pub/Sub usage by adding more shards." Subscribers can connect to the slot's primary or any of its replicas.
Four constraints that rarely get mentioned:
- No patterns. Sharded pub/sub has no equivalent of
PSUBSCRIBE— which is also whySPUBLISHis plain O(N) with no pattern term. Moving to sharded means giving patterns up entirely. - One slot per call. "All shard channels in a single SSUBSCRIBE call must belong to the same slot." Cross-slot subscriptions need separate calls.
-MOVEDredirects apply.SSUBSCRIBEcan redirect like any slot-bound command, so the client must handle it.- Separate unsubscribe. Global channels and shard channels are unsubscribed independently, and sharded messages arrive as a distinct
smessagepush type rather thanmessage.
Valkey has sharded pub/sub too. Worth stating precisely: Valkey forked from Redis at 7.2, after the 7.0 feature landed, so every Valkey release ever published has included it.
Subscribed Clients, RESP2 and RESP3
Under RESP2, subscribing puts the connection into a restricted mode. A subscribed client may issue only nine commands: PING, PSUBSCRIBE, PUNSUBSCRIBE, QUIT, RESET, SSUBSCRIBE, SUBSCRIBE, SUNSUBSCRIBE and UNSUBSCRIBE. (Older articles list seven — they predate the sharded commands.)
The reason is protocol-level. In RESP2 a pushed message and a command reply are indistinguishable on the wire, so the connection has to be locked down to keep the stream unambiguous. RESP3 tags push messages with a distinct type, which removes the problem: "if RESP3 is used (see HELLO), a client can issue any commands while in the subscribed state."
The practical consequence is about connection pooling. On RESP2 a subscribed connection cannot run ordinary commands, so every subscriber needs a connection of its own — which is why client libraries allocate one per subscriber rather than borrowing from the pool. Note that RESP3 remains opt-in: connections still start in RESP2 mode and must send HELLO 3 to upgrade.
One more operational detail: the server's timeout setting does not apply to pub/sub clients, because an idle push connection is the normal state rather than a sign of an abandoned client.
Keyspace Notifications Ride on Pub/Sub
Redis keyspace notifications are delivered over pub/sub — they are literally PUBLISH calls. Running DEL mykey on database 0 is, in the docs' words, "exactly equivalent to" publishing to __keyspace@0__:mykey and __keyevent@0__:del.
Their cluster behaviour is the exact inverse of everything above, and it catches people out: "unlike regular Pub/Sub communication in a cluster, events' notifications are not broadcasted to all nodes… This means that to receive all keyspace events of a cluster, clients need to subscribe to each of the nodes." Ordinary publishes fan out everywhere; keyspace events stay on the node that owns the key. And because they ride on pub/sub, they inherit at-most-once delivery — an expired event that fires while your client is reconnecting is gone for good. See Redis keyspace notifications for the flag table and the delivery guarantees, and Redis notifications in Java for the Java setup.
Redis Pub/Sub in Java With Redisson
Redisson exposes pub/sub through RTopic, with automatic serialization and listener management:
RTopic topic = redisson.getTopic("news.sport");
int listenerId = topic.addListener(ScoreUpdate.class,
(CharSequence channel, ScoreUpdate msg) -> handle(msg));
// from another thread or JVM
long clientsReached = topic.publish(new ScoreUpdate("2-1"));
Listeners are re-subscribed automatically after a reconnection or failover — but Redisson is candid about the limit, and it is the same one the whole page has been building toward: "All messages sent during absence of connection are lost." Automatic re-subscription restores the subscription, not the missed messages.
RPatternTopic wraps PSUBSCRIBE, and its listener receives the matched pattern alongside the channel:
RPatternTopic topic = redisson.getPatternTopic("news.*");
topic.addListener(ScoreUpdate.class,
(CharSequence pattern, CharSequence channel, ScoreUpdate msg) -> handle(channel, msg));
RShardedTopic implements sharded pub/sub. As Redisson puts it, messages published through it "aren't broadcasted across all nodes as for RTopic object," which reduces both bandwidth and CPU load across the cluster:
RShardedTopic topic = redisson.getShardedTopic("orders.eu");
topic.publish(new OrderEvent(4711));
When Losing Messages Is Not Acceptable
Everything above inherits at-most-once delivery, because that is what pub/sub is. Redisson offers two exits, and both are built on Redis Streams rather than pub/sub.
Redisson PRO's Reliable PubSub (RReliablePubSubTopic) adds a topic–subscription–consumer model with explicit acknowledgment, visibility timeouts, automatic redelivery, delivery-attempt limits, dead letter topics, deduplication and seek-by-timestamp replay. That is at-least-once delivery with deduplication — a genuine step up from at-most-once, and the right tool for order fulfilment or ledger events. See Reliable PubSub for Valkey and Redis for the full walkthrough and Reliable PubSub vs. native pub/sub for the feature-by-feature comparison. For a working RTopic implementation, see how to use Redis pub/sub in Java.
Redis Pub/Sub: Frequently Asked Questions
What Is Redis Pub/Sub Used For?
Real-time fan-out where messages matter only at the moment they happen: live dashboards, chat and presence updates, cache-invalidation signals between application instances, and notifying workers that something changed. It suits cases where a missed message costs nothing, because a missed message is exactly what happens when a subscriber is offline.
Does Redis Pub/Sub Guarantee Message Delivery?
No. Redis Pub/Sub is at-most-once: a message is delivered once if at all, and the documentation states that if a subscriber cannot handle it, "the message is forever lost." There is no acknowledgment, no retry and no persistence. If you need delivery guarantees, use Redis Streams, which persist entries and track per-consumer acknowledgment.
What Happens to Messages if a Subscriber Is Offline?
They are lost. Redis does not queue messages for absent subscribers — a message is delivered to whoever is connected at that instant and then discarded. If no client is subscribed to a channel when something is published there, the message simply disappears. Reconnecting restores the subscription but never the missed messages.
What Is the Difference Between Redis Pub/Sub and Redis Streams?
Pub/Sub stores nothing and delivers at most once; Streams store an append-only log with per-message acknowledgment, consumer groups and replay from any point. Pub/Sub is faster and simpler with no memory growth. Streams cost memory and require trimming, but survive consumer restarts. Choose Pub/Sub for live signals, Streams for work that must not be lost.
What Is Sharded Pub/Sub and When Should I Use It?
Sharded Pub/Sub, added in Redis 7.0, uses SSUBSCRIBE and SPUBLISH to confine message propagation to a single cluster shard instead of broadcasting to every node. Use it when pub/sub traffic on a Redis Cluster is saturating the cluster bus. The trade-off is that shard channels do not support pattern subscriptions.
Can You Use Redis Pub/Sub as a Message Queue?
Not safely. A queue implies messages wait for a consumer and are acknowledged once processed; pub/sub does neither. A restart, a network blip or a slow consumer silently loses work. Redis Streams or a Redis list-backed queue are the appropriate structures, and both are supported natively.
Why Did My Redis Subscriber Get Disconnected?
Most often because it fell behind. Redis enforces client-output-buffer-limit pubsub 32mb 8mb 60: a subscriber is disconnected immediately at 32 MB of buffered output, or after 60 continuous seconds above 8 MB. There is no back-pressure — the publisher never slows down — so a consumer that cannot keep up is dropped rather than throttled.