How it works
A publisher sends an event to a named topic, such as order-created or room-42. The event usually includes an ID, an entity key, a type, and a payload; the publisher does not address individual consumers.
Consumers register subscriptions to topics or matching filters. For example, an order-created event can reach separate subscriptions for notifications, fulfillment, and analytics, so each service processes the event independently.
Distinguish a subscription from its workers. Each independent subscription receives the matching event, while workers sharing one subscription or consumer group generally divide the work. Putting analytics and fulfillment in the same competing-consumer group would send each event to only one of them.
Choose whether subscriptions are ephemeral or durable. An ephemeral subscriber may miss events while disconnected; a durable subscription can retain pending messages or track a position in a retained log. Replay is limited by retention and the broker's subscription rules.
Define acknowledgments and failure behavior. With at-least-once delivery, a consumer processes an event and acknowledges it, but a crash between those steps can cause redelivery. Use idempotent processing, bounded retries, and a dead-letter path where appropriate.
For live delivery, backend subscriptions often feed WebSocket gateways, which fan events out to connected clients. If several gateways host viewers of room-42, every relevant gateway must receive its updates; one shared competing-consumer group across those gateways would not broadcast them correctly.
A worked example
Broadcasting a hot stock symbol
Suppose 100,000 viewers watch one stock symbol through 100 WebSocket gateways, each serving 1,000 viewers. The symbol produces 20 updates per second, each 200 bytes. Give every interested gateway its own logical subscription; sharing one competing-consumer group would deliver each update to only one gateway. Delivering one copy per gateway uses about 400 KB/s from the broker, while gateway-to-client payload traffic totals about 400 MB/s, excluding protocol overhead. Bound each client's outgoing buffer. If the product needs only the latest quote, replace queued older quotes with newer ones and include a source sequence number. Keep durable trade history separate because dropping intermediate quotes would not satisfy a requirement to deliver every trade.
Trade-offs to say out loud
- Independent consumers, less immediate coordination
- Services can react and scale independently, but publishing an event does not mean downstream processing has completed.
- Fan-out multiplies delivery work
- One publication can create many deliveries, so size broker bandwidth, subscription state, and client egress rather than counting only incoming events.
- Durability costs storage and recovery capacity
- Retained events support outage recovery and replay, but require retention limits and enough capacity for consumers to catch up.
- Retries create duplicate-processing risks
- At-least-once delivery needs idempotent side effects, and broker guarantees alone do not make an external payment or notification happen exactly once.
- Ordering limits parallelism
- Per-key or per-partition ordering is practical, but a hot key can bottleneck and concurrent processing or retries can reorder completed effects.
- Slow consumers need an explicit policy
- Use bounded buffering, durable backlog, disconnection, or permitted dropping and conflation so one lagging subscriber cannot exhaust shared resources.
When to reach for it
- Several independent services must react to the same business event without the producer calling each service directly.
- Many users subscribe to changing data such as chat rooms, document edits, comments, or stock prices.
- Consumers need independent progress, retry policies, or replay without forcing the producer to wait for them.
- Polling would create excessive repeated reads or fail the required update-latency target.
How to bring it up in the interview
- Start with the delivery topology: identify publishers, topics, independent subscriptions, and workers within each subscription. Interviewers often probe whether you have accidentally designed load balancing instead of broadcast.
- State what losing an event means. Separate disposable presence updates from durable chat messages, then explain retention, acknowledgment, and reconnect behavior for each.
- Name the ordering scope, such as conversation ID or stock symbol, and explain how partitioning preserves it. Expect follow-ups about hot keys, retries, and consumer failover.
- Estimate deliveries and bytes after fan-out, then describe per-subscriber buffering and lag limits. Explain whether slow clients receive every event, only the latest state, or a reconnect-and-resync instruction.
- Explain the database-to-publisher boundary when an event represents a committed write. An outbox can prevent missing publication, while event IDs and idempotent consumers handle duplicate publication.
Common mistakes
- Assuming every worker receives every event even when the workers share one competing-consumer subscription.
- Treating pub-sub as inherently durable, replayable, or exactly-once without specifying the broker configuration and processing boundaries.
- Using ephemeral live delivery as the only storage for messages that offline users must receive later.
- Promising global ordering while partitioning and processing events concurrently.
- Ignoring fan-out bandwidth, unbounded client buffers, and authorization checks when subscriptions are created or permissions change.
Where it comes up
Interview questions where publish-subscribe is part of a strong answer, and why.
- Design a chat app like WhatsAppPub-sub routes conversation events to the servers holding recipient connections, while durable storage supports offline delivery and reconnects.
- Design Google DocsPer-document subscriptions distribute accepted edits and cursor updates to connected collaborators without making live fan-out the source of truth.
- Design a real-time stock price feedSymbol subscriptions, hierarchical fan-out, and bounded slow-client delivery are central to broadcasting fresh quotes at global scale.
- Design Facebook live commentsPer-stream pub-sub distributes comments across gateways while the design must handle hot streams, ordering, and reconnect gaps.
- Design a distributed message log like KafkaIndependent consumer groups and retained-log positions provide durable publish-subscribe behavior with explicit replay and retention limits.
- Design Facebook likes at scaleLive count delivery requires broadcasting aggregated updates to many viewers without sending every underlying like event to every client.
Questions people ask
What is the difference between pub-sub and a message queue?
Pub-sub distributes an event to multiple independent subscriptions. A work queue usually distributes each task to one worker among competing consumers. A broker can support both: independent subscriptions provide fan-out, and workers within each subscription share its processing load.
Does publish-subscribe guarantee message delivery?
Not by itself; pub-sub describes how producers and consumers are connected. Delivery depends on persistence, retention, acknowledgments, retries, and failure handling. Even a durable subscription can lose its recovery window if its backlog outlives retention.
Is pub-sub the same as WebSockets?
No. Pub-sub is a messaging pattern, while WebSocket is a persistent, bidirectional connection protocol. A common design uses pub-sub between backend services and gateways, then WebSockets between gateways and clients.