skip to content

Pub/Sub Semantics

You will learn why classic Redis pub/sub is at-most-once by design: no persistence, no replay, and a disconnected subscriber simply misses messages. Interviewers ask because knowing what pub/sub does NOT guarantee is the whole point of the question.

part ofRedisoverview, primer and where to startread it →
on this pageshow

questions

4

In Redis, what delivery guarantee does a message sent with the PUBLISH command carry, and what happens to messages published while a subscriber's connection is down?

level: middleimportance: must knowfreq 62%

answer

  1. No key, no TTL, no RDB/AOF
  2. Delivery decided at PUBLISH time
  3. Reconnect gap = silent loss
  4. Buffer limit kills slow subscriber
  5. Publish a hint, not the state

basics

~20 s

Fire-and-forget, at-most-once. PUBLISH hands the message only to clients subscribed at that instant and stores nothing. A subscriber that is disconnected, still reconnecting, or killed for a full output buffer misses those messages permanently: no replay, no offsets, no acknowledgement.

solid answer

~50 s

Redis Pub/Sub is a routing feature, not a queue. `PUBLISH channel msg` looks up the clients currently subscribed to that channel, copies the message into each one's output buffer, and returns how many it reached. Nothing is written into a data structure, nothing lands in RDB or AOF, and there is no offset or acknowledgement, so the guarantee is at-most-once. That gives three concrete loss windows: a subscriber that has not issued SUBSCRIBE yet never sees earlier messages; a subscriber whose TCP connection drops loses everything published until it reconnects and re-sends SUBSCRIBE, and that resubscribe gap is real; and a slow subscriber whose pub/sub output buffer exceeds `client-output-buffer-limit` is disconnected by the server, silently dropping what was queued. So Pub/Sub fits notifications you can afford to miss: cache-invalidation pings, presence, "something changed, go re-read the source of truth". It is the wrong transport for state you cannot reconstruct elsewhere.

code

text · 11 lines
text
# terminal 1 (no subscriber yet)
> PUBLISH news "first"
(integer) 0            # zero receivers, message discarded

# terminal 2
> SUBSCRIBE news
1) "subscribe" 2) "news" 3) (integer) 1

# terminal 1
> PUBLISH news "second"
(integer) 1            # only this one is seen; "first" is gone forever

go deeper

for a junior

Know the core recall: PUBLISH reaches only clients subscribed right now, nothing is stored, and an offline subscriber loses those messages.

for a middle

Explain why: the subscriber registry is transient, there is no id or offset, and name the three loss windows (late subscribe, disconnect, buffer eviction).

for a senior

Talk about operational consequences: the resubscribe gap on every deploy or failover, silent drops from output-buffer limits, and designing messages as hints backed by TTLs.

for a principal

Frame it as a delivery-guarantee choice: Pub/Sub buys near-zero-cost fan-out at the price of at-most-once, so decide per data class whether staleness is bounded and self-healing, and push anything else onto a stored, replayable mechanism.

## What PUBLISH actually does When a client sends `SUBSCRIBE news`, Redis records it in an in-memory dictionary mapping the channel name to the set of currently subscribed clients. `PUBLISH news "hello"` looks up that set, copies the message bytes into each subscriber's client output buffer, and returns the number of receivers. The channel itself is not an object in the keyspace: it has no key, no TTL, no memory footprint beyond the subscriber registry, and `KEYS`/`SCAN` will never show it. Once the message has been written into the connected sockets' buffers, Redis forgets it. ## Why that means at-most-once At-most-once means each message is delivered zero or one time to a given consumer, and the sender cannot tell which. Redis provides no message id, no consumer cursor, no acknowledgement command, and no retry. Compare that with a durable log, where each message has a position that a consumer can rewind to; Redis Pub/Sub has no position to rewind to, because the message never existed as stored data. ## The three loss windows 1. **Late subscribe.** Delivery is decided at PUBLISH time. A consumer that starts one millisecond later gets nothing that was published before its SUBSCRIBE was processed. 2. **Disconnection.** If the TCP connection drops (network blip, server restart, failover to a replica, proxy timeout), the subscription is gone with it. Client libraries reconnect and replay the SUBSCRIBE commands automatically, which hides the failure but not the gap: everything published between the drop and the resubscribe is lost, and the application is not told. 3. **Slow consumer eviction.** Redis will not grow a subscriber's output buffer forever; when the pub/sub output-buffer limit is crossed, the server closes that client. From the publisher's side nothing failed. ## Persistence, replication and failover Pub/Sub messages are never persisted: they are not part of RDB snapshots or the AOF, so a restart delivers nothing that was in flight. They are propagated to replicas and, in a cluster, across the cluster bus, so a client subscribed on a replica does see messages published on the primary; that is fan-out, not durability. After a failover, subscribers connected to the old primary are disconnected and must resubscribe to the new one. ## Designing around it The safe pattern is to treat a published message as a *hint*, never as the data. Publish "user 42 changed", not the new user record, and have the subscriber re-read the authoritative store. Then a missed message costs a slightly stale cache until the next event or TTL, instead of a permanently wrong state. If the consumer must not miss anything, Pub/Sub is the wrong primitive and you need a stored, replayable structure instead. A useful check in interviews: ask what happens if the subscriber process is redeployed. If the answer is "it resubscribes and continues", the design has already accepted a gap on every deploy.

  • Your cache invalidations travel over Redis Pub/Sub and a subscriber restarts during a deploy. What can go wrong and how do you contain it?
    Any invalidation published while the process was down is lost, so that node can serve a stale cache entry indefinitely. Contain it by always setting a bounded TTL on cached entries so staleness self-heals, and by re-warming or flushing the local cache on startup. If a specific entry must never be stale, read it through to the source of truth instead of relying on the notification.
  • Does the integer returned by PUBLISH prove the message was handled?
    No. It counts the clients the message was written out to, not applications that processed it. In Redis Cluster it counts only receivers attached to the node you published on, even though the message is forwarded to other nodes. A client can be killed or crash right after the write, so treat the number as a rough presence or debugging signal, mainly useful to catch a channel-name typo returning 0.

It is a radio broadcast, not voicemail. Whoever has the radio on hears it; whoever is out of the room hears nothing and there is no recording to play back.

saying these in an interview costs you the question

  • Saying Redis Pub/Sub is "at-least-once" or that Redis retries delivery
  • Believing messages are buffered for a subscriber that is offline and delivered on reconnect
  • Thinking AOF or RDB persistence protects published messages across a restart
  • Treating a non-zero PUBLISH return value as an application-level acknowledgement
  • Publishing the only copy of important state instead of a hint to re-read the source

context

open as a page

After a Redis client issues the SUBSCRIBE command, what state is that connection in, which commands can it still run, and how does it get back to normal?

level: juniorimportance: should knowfreq 45%

basics

~20 s

Under RESP2 the connection enters subscriber mode: it may only run SUBSCRIBE/UNSUBSCRIBE (and their pattern and sharded variants), plus PING, RESET and QUIT. Other commands error. Leave by unsubscribing from everything, or with RESET. Under RESP3 the restriction is gone.

open as a page

In Redis Cluster, how does a message sent with PUBLISH reach subscribers on other nodes, why does that become a scaling problem, and what do SPUBLISH and SSUBSCRIBE do differently?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Classic PUBLISH is broadcast to every node over the cluster bus so any subscriber anywhere receives it, which makes pub/sub traffic grow with cluster size and never shard. Sharded pub/sub (Redis 7.0) hashes the channel name to a slot: SPUBLISH goes only to that shard's primary and replicas, and SSUBSCRIBE must target that node.

open as a page

A Redis subscriber consumes published messages more slowly than they are produced. What does the Redis server eventually do about it, which configuration governs that, and what does the application see?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Redis buffers undelivered messages per client, and when the pub/sub client-output-buffer-limit is crossed (default hard 32mb, soft 8mb for 60s) it closes that connection. The subscriber sees a dropped connection, reconnects, resubscribes, and silently loses everything queued. Publishers see nothing.

open as a page