Real-Time APIs · Scaling Real-Time Systems
Fan-Out with Pub/Sub Backends
Deliver messages to users connected to many server instances.
Each user connects to one of many gateway instances; a message for a room or user must reach the right instances. Use a pub/sub backbone: Redis pub/sub or Redis Streams, NATS, Kafka (for durable fan-out), or a managed service. Route by channel/topic (room, user, tenant). For very large audiences (millions of subscribers to one channel), use hierarchical fan-out (edge tiers) and batching.
Fan-out backbones
| Backbone | Durability | Latency | Notes |
|---|---|---|---|
| Redis pub/sub | None (fire-and-forget) | Very low | Simple; lost if subscriber offline |
| Redis Streams | Yes (until trimmed) | Low | Catch-up after reconnect |
| NATS / JetStream | Optional (JetStream) | Very low | Subject-based routing |
| Kafka | Yes | Low–moderate | Great for durable feeds, heavier ops |
| Managed (Ably, Pusher) | Yes (history) | Low, global | Presence, history built in |
Client ─WS─► Gateway A ─┐ ┌─► Gateway B ─WS─► Client (same room)
├─► publish room:42 ─┤
Client ─WS─► Gateway A ─┘ (Redis/NATS) └─► Gateway C ─WS─► Client
Gateways subscribe only to channels their connected clients joined.
Common pitfalls
- Every gateway subscribing to every channel.
- Fire-and-forget pub/sub for messages that must not be lost.
- No persistence for chat history (store separately).
Key points
- Pub/sub between gateways
- Subscribe per active channel
- Durable store for history
Further reading: Redis: Pub/Sub
Practice questions
Why is Redis pub/sub alone insufficient for chat history?
Answer
It's fire-and-forget: messages aren't stored, so disconnected users miss them; persist messages in a database and use pub/sub only for live delivery.
How do gateways avoid receiving every message in the system?
Answer
They subscribe only to channels (rooms/users) that their connected clients have joined, and unsubscribe when the last client leaves.
Open in the app to mark lessons complete, take notes and track your progress.