Pub/Sub messaging

Redis · Practical · 9 min

Pub/Sub is the simplest way to push real-time events, such as chat or cache invalidations, to many processes.

Pub/Sub decouples senders from receivers. Subscribers call SUBSCRIBE news (or PSUBSCRIBE news.* for glob patterns) and the connection enters a listening mode. Publishers call PUBLISH news "hello", which returns how many subscribers received it.

Delivery is fire-and-forget, at most once:

  • messages are not stored; a subscriber that is offline or reconnecting misses them,
  • there is no acknowledgement or replay,
  • a slow subscriber whose output buffer grows past the limit is disconnected.

That's fine for ephemeral signals: chat typing indicators, live dashboards, telling every app server to drop a local cache entry, or WebSocket fan-out across servers. When you need durability, replay or work distribution among consumers, use streams.

A subscribed connection can only run subscription commands (in RESP2), so client libraries use a dedicated connection for it. Channel names are global across logical databases.

In a Redis Cluster, classic PUBLISH is broadcast to every node. Sharded Pub/Sub (SSUBSCRIBE/SPUBLISH, Redis 7.0+) maps a channel to a hash slot so messages stay on one shard, which scales much better.

Keyspace notifications (notify-keyspace-events) use Pub/Sub to announce events like key expiry, but they inherit the same fire-and-forget delivery.

Example

import threading, time
import redis

r = redis.Redis(decode_responses=True)
p = r.pubsub()
p.subscribe("news")
p.psubscribe("alerts.*")

def listen():
    for msg in p.listen():
        if msg["type"] in ("message", "pmessage"):
            print(msg["channel"], msg["data"])

threading.Thread(target=listen, daemon=True).start()
time.sleep(0.1)
print(r.publish("news", "hello"))        # 1 subscriber received it
r.publish("alerts.disk", "90% full")     # matched by the pattern
r.publish("nobody-listens", "lost")      # returns 0, message is gone
time.sleep(0.1)
# news hello
# alerts.disk 90% full

Remember

  • SUBSCRIBE/PSUBSCRIBE receive, PUBLISH sends and returns receiver count
  • At-most-once: no storage, no replay, no acks
  • Use a dedicated connection for subscribing
  • In a cluster prefer sharded Pub/Sub (SPUBLISH/SSUBSCRIBE)

Watch out for

  • Using Pub/Sub as a job queue: jobs published while workers restart are lost.

Check yourself

  1. A worker restarts for 3 seconds while messages are published on its channel. What happens to those messages?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: redis.io/docs/latest/develop/interact/pubsub/