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.