Chapter 16 · Pub/Sub, Keyspace Notifications, and Messaging Tradeoffs
PUBLISH/SUBSCRIBE and Pattern/Shard Channels: Ephemeral Fan-Out Semantics
Build a precise Redis Pub/Sub mental model from channels, patterns, and sharded channels through fan-out, subscriber state, duplicate delivery paths, RESP behavior, and Cluster-aware routing.
Learning outcomes
AtlasMart wants an order-status dashboard to update immediately when an order changes. The durable order record already exists; the new requirement is only to wake connected dashboards quickly. That is the right starting point for Redis Publish/Subscribe (Pub/Sub): a real-time fan-out transport for clients that are online now, not an event log.
Define publisher, subscriber, channel, pattern subscription, fan-out, ephemeral delivery, and at-most-once semantics before using Redis commands.
Use PUBLISH/SUBSCRIBE and PSUBSCRIBE and explain live subscriber counts, message ordering, and overlapping-subscription duplicates.
Explain RESP2 subscribed-state restrictions and why RESP3 changes what a subscribed connection may issue without making Pub/Sub durable.
Use SSUBSCRIBE/SPUBLISH as Redis 7.0+ sharded Pub/Sub APIs and separate standalone API evidence from Redis Cluster routing/scaling evidence.
Choose Pub/Sub only when losing messages during disconnect is acceptable or recoverable from authoritative state.
All Chapter 16 mandatory labs reuse the disposable Chapter 01
environment: Redis Open Source 8.10.1 from pinned
Docker image redis:8.10.1, container
atlasmart-redis-ch01, standalone topology,
endpoint 127.0.0.1:6379, TLS disabled only
because traffic is loopback-local, default ACL user disabled,
named academy-admin and
atlasmart-app users, logical database 0, AOF with
appendfsync everysec plus RDB snapshots,
persistent /data, and no explicit
maxmemory/eviction policy. Python examples target
redis-py 8.1.0. The Chapter 01 application ACL
intentionally does not assume Pub/Sub command permissions, so
Pub/Sub/configuration demonstrations use
academy-admin until Lesson 5 creates a temporary
least-privilege Chapter 16 user. Fixtures stay under
atlasmart:ch16:.
1. Pub/Sub has no key and no replay cursor
A channel is a name used only for message
routing. A publisher sends a payload to that
name with PUBLISH; Redis immediately pushes the
payload to clients currently subscribed to that channel. A
subscriber is a live connection that asked
Redis to receive those pushes. The message is not a Redis
String, Stream entry, List item, or persisted queue record, so
GET, SCAN, RDB, and AOF do not give
you a Pub/Sub history to replay.
Redis Pub/Sub is at-most-once: if a subscriber is disconnected, unable to process a delivered message, or reconnecting after failover, Redis does not later replay the missing publication. Durable state or a replayable log must carry correctness.
2. Exact channels: one publication, every active exact subscriber
PUBLISH sends one payload to an exact channel.
SUBSCRIBE puts a connection into subscription
state. PUBSUB NUMSUB reports exact-channel
subscribers but excludes pattern subscriptions, which is why it
is useful evidence but not a total audience count.
PUBLISH itself returns the number of clients it
sent the message to; in Redis Cluster that return count is
node-local and should not be mistaken for a cluster-wide
delivery receipt.
docker exec -it -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin SUBSCRIBE atlasmart:ch16:l1:orders# Keep this terminal open. The confirmation shows subscription count 1.
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PUBSUB NUMSUB atlasmart:ch16:l1:ordersdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PUBLISH atlasmart:ch16:l1:orders order-1001:paid# Terminal A should receive a message frame. PUBLISH should report at least the active exact subscriber in this standalone lab.
3. Pattern subscriptions are routing rules, not stored topics
PSUBSCRIBE accepts glob-style patterns such as
atlasmart:ch16:l1:order:*. Redis compares
publications against active patterns at publish time. Pattern
matching expands routing convenience but also adds work:
PUBLISH complexity includes the total number of
subscribed patterns. A pattern is not a durable topic
declaration and does not reserve future messages.
docker exec -it -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PSUBSCRIBE 'atlasmart:ch16:l1:order:*'# In another terminal publish to atlasmart:ch16:l1:order:1002.
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PUBLISH atlasmart:ch16:l1:order:1002 shippeddocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin PUBSUB NUMPAT# NUMPAT counts active pattern subscriptions; it is different from NUMSUB.
4. Boundary case: one client can receive the same publication twice
At-most-once describes Redis handling of each Pub/Sub delivery
path; it does not promise “one application callback per business
payload.” If one client subscribes both to exact channel
foo and matching pattern f*, Redis
pushes both a message frame and a
pmessage frame for one
PUBLISH foo .... Applications that intentionally
combine exact and pattern subscriptions must deduplicate at a
higher semantic layer if duplicates matter.
| Subscription on one connection | Publication | Client-visible pushes |
|---|---|---|
| SUBSCRIBE foo | PUBLISH foo X | one message frame |
| PSUBSCRIBE f* | PUBLISH foo X | one pmessage frame |
| Both exact + pattern | PUBLISH foo X | two pushes via two matching routes |
5. RESP2 versus RESP3 changes connection behavior, not delivery guarantees
The Redis Serialization Protocol (RESP) frames commands and
replies. Under RESP2, a subscribed connection is restricted to
subscription-control commands plus a small allowed set such as
PING, RESET, and QUIT.
With RESP3, Redis permits arbitrary commands while the
connection is subscribed. That is a protocol/client capability
boundary only: RESP3 does not add message persistence,
acknowledgments, or replay. redis-py normally gives a
PubSub object its own connection, which remains the
clearest application design.
HELLO 2SUBSCRIBE atlasmart:ch16:l1:resp-demo# RESP2 subscribed state restricts ordinary commands on this connection.# In a fresh connection: HELLO 3, then SUBSCRIBE; RESP3 permits commands while subscribed, but Pub/Sub remains ephemeral.
6. Sharded Pub/Sub is a Cluster scaling mechanism
Redis 7.0 introduced sharded Pub/Sub. Shard
channels are hashed to Redis Cluster slots using the same slot
algorithm used for keys. SSUBSCRIBE,
SPUBLISH, and SUNSUBSCRIBE keep
message propagation within the owning shard instead of globally
propagating every publication across the Cluster bus. In
Cluster, all shard channels in one SSUBSCRIBE call
must map to the same slot; different slots require separate
subscriptions.
COMMAND INFO SSUBSCRIBE SPUBLISH PUBSUBPUBSUB SHARDNUMSUB atlasmart:ch16:l1:shard:{eu}# The standalone Chapter 01 lab can verify command availability/API behavior.# It cannot prove Cluster slot routing, cross-node propagation cost, failover behavior, or horizontal scaling.
Do not report a standalone SSUBSCRIBE/SPUBLISH exercise as a Redis Cluster benchmark. Cluster routing, MOVED redirects, shard ownership, replicas, and bus traffic require an actual Cluster topology and Cluster-aware client.
7. Why ordinary and sharded channels must not be mixed casually
PUBLISH/SUBSCRIBE and
SPUBLISH/SSUBSCRIBE are separate
routing families. Publishing normally does not “also send” to a
shard subscription with the same text name, and sharded
publication does not become global publication. Choose one model
per logical notification channel and encode that choice in
naming/client code so topology changes do not silently split
audiences.
| Need | Prefer | Reason |
|---|---|---|
| Small/global fan-out | PUBLISH/SUBSCRIBE | Simple global semantics; Cluster propagates globally |
| Cluster-scaled local fan-out | SPUBLISH/SSUBSCRIBE | Propagation stays within owning shard |
| Glob matching | PSUBSCRIBE | Pattern matching exists only in ordinary Pub/Sub family |
| Replay/acknowledgment | Redis Streams or another durable log | Pub/Sub has no persisted consumer state |
8. Lab verification and bounded reset
Stop the interactive subscriber terminals with Ctrl-C. There is no Pub/Sub key to delete because channels are not stored data. Verify the subscriber counts drop after disconnect and then clean only the small state fixtures created for comparison.
PUBSUB NUMSUB atlasmart:ch16:l1:orders atlasmart:ch16:l1:order:1002PUBSUB NUMPATPUBSUB SHARDNUMSUB atlasmart:ch16:l1:shard:{eu}# Counts are live connection state, not message-history counts.
UNLINK atlasmart:ch16:l1:state
9. Production judgment
Pub/Sub is appropriate for live dashboards, invalidation hints, typing indicators, telemetry fan-out, and other signals where a missed message is either acceptable or repaired by re-reading authoritative state. It is a poor fit for payments, fulfillment transitions, audit records, queue work, or any workflow whose correctness requires replay/acknowledgment. Monitor subscriber counts, reconnects, client output buffers, publication rate, callback latency, and Cluster propagation design. Restrict channel ACLs; channel names are not tenant authorization by themselves.
Check your understanding
- What happens to a message published while a subscriber is offline?
- Does PUBSUB NUMSUB include PSUBSCRIBE listeners?
- Can one client receive one publication twice?
- What does sharded Pub/Sub change?
- Does RESP3 make Pub/Sub durable?
Review the answers
It is lost to that subscriber; Redis Pub/Sub has no replay cursor or stored history.
No. NUMSUB reports exact-channel subscribers and excludes pattern subscriptions.
Yes, if multiple active subscription routes match, such as exact plus matching pattern.
In Redis Cluster it hashes shard channels to slots and limits propagation to the owning shard rather than the whole cluster.
No. It changes subscribed-connection command capability, not delivery persistence or replay.
10. Summary and next step
Redis Pub/Sub is live routing state attached to connections. Exact channels, glob patterns, and sharded channels change how messages fan out, but none creates a durable event log. Lesson 2 deliberately disconnects a subscriber and slows another one so the at-most-once and backpressure boundaries become observable.
Authoritative references
- Redis Open Source 8.10 release notes
- Redis Pub/Sub
- Redis Pub/Sub use case
- Redis Pub/Sub with redis-py
- PUBLISH
- SUBSCRIBE
- PSUBSCRIBE
- UNSUBSCRIBE
- PUNSUBSCRIBE
- SSUBSCRIBE
- SPUBLISH
- SUNSUBSCRIBE
- PUBSUB CHANNELS
- PUBSUB NUMSUB
- PUBSUB NUMPAT
- PUBSUB SHARDCHANNELS
- PUBSUB SHARDNUMSUB
- Redis keyspace notifications
- Redis subkey notifications
- CONFIG GET
- CONFIG SET
- CLIENT LIST
- CLIENT SETNAME
- Redis client output-buffer limits
- Redis Streams
- Redis streaming use case
- XADD
- XREADGROUP
- XPENDING
- XACK
- Redis ACLs
- ACL SETUSER
- ACL DRYRUN
- Redis Cluster specification
- Redis replication
- Redis Sentinel
- Redis persistence
- redis-py documentation
- redis-py 8.1.0 on PyPI
- Redis licenses