Real-time updates pattern — protocols and fan-out tiles

Real-time updates for system design interviews

The real-time updates pattern end to end: two hops (client protocols + server fan-out), networking basics, polling vs long poll vs SSE vs WebSockets vs WebRTC, L4/L7 load balancers, consistent hashing vs pub/sub, deep dives, and when to stay simple.

Why real-time updates show up everywhere

From Ticketmaster seat holds to WhatsApp messages to Google Docs keystrokes to ChatGPT token streams — users expect to see changes the moment they happen. Standard HTTP request/response closes after each exchange. That model breaks when the server must speak first.

Many candidates (even with 10+ years) never built the push path themselves — a specialized team did it once. Interviews still expect you to choose protocols and fan-out wisely. This post is that bridge. Pair with Networking essentials and the short version in Common patterns.

01Hop 1

Poll · SSE · WS · WebRTC.

02Hop 2

DB poll · hash · pub/sub.

03Infra

L4/L7 · sticky · deploys.

04Deep dives

Reconnect · celebrity · order.

The solution: two hops

Source to server hop 2 then client channel hop 1 to UI.
Hop 1 = client channel. Hop 2 = how the owning server learns about the event.
  1. Hop 1 — Client↔server: How does the server deliver bytes to the browser/app? (polling, long poll, SSE, WebSocket, WebRTC)
  2. Hop 2 — Source→server: How does the right connection-holding machine learn that something changed? (DB pull, consistent hash ownership, pub/sub)

Networking 101 for realtime

Realtime interviews are networking interviews in disguise. Three layers matter most:

OSI-style stack highlighting L3 IP, L4 TCP, and L7 application protocols.
Interview focus: L3 addressing, L4 connections, L7 protocols — everything else is background.
  • L3 IP — packets, routing, best-effort (loss/reorder possible).
  • L4 TCP / UDP — TCP: connection, ordered, reliable (handshake cost + state). UDP: fire-and-forget (WebRTC media often rides here).
  • L7 HTTP / WS / WebRTC — application protocols on top of those transports.

HTTP request lifecycle (why connections matter)

DNS → TCP 3-way handshake (SYN / SYN-ACK / ACK) → HTTP request/response → TCP teardown (FIN/ACK). Each RTT adds latency; each connection is state both sides maintain. HTTP keep-alive amortizes setup across polls — critical if you stay on polling.

TCP handshake, HTTP GET/response, and TCP teardown across IP TCP HTTP layers.
One short HTTP exchange still costs a handshake + teardown — why keep-alive and persistent sockets matter.

L4 vs L7 load balancers

L4L7
SeesIP:port / TCPHTTP path, headers, cookies
TCP sessionClient↔backend stickyTerminates; new backend conn
Best forWebSockets, raw performanceHTTP routing, API gateway-like
Realtime noteNatural for persistent socketsNeed explicit WS/SSE support
Client through L4 load balancer to server on one sticky TCP session.
L4 (e.g. AWS NLB): one TCP pipe client↔backend — natural for WebSockets.
L7 load balancer terminates client TCP and opens a separate connection to the backend.
L7 (e.g. AWS ALB): reads HTTP, routes on path/headers — but breaks the single-TCP illusion.

Hop 1: client–server protocols

Five protocols from simple poll to WebRTC.
Climb the ladder only when product latency and directionality force it.
Decision flowchart for polling SSE WebSocket.
Memorize this flowchart for interviews.

Simple polling — the baseline

Client repeatedly polls server and database while updates are written to the DB.
Pull model: clients ask; writers just land in the DB — simple, but QPS adds up.

Client GET /updates on an interval. Not "true" realtime — often good enough. Chat: "messages since cursor X every 2s."

async function poll() {
  const res = await fetch('/api/updates?since=' + cursor);
  const data = await res.json();
  processData(data);
}
setInterval(poll, 2000);
  • Pros — simple, stateless, works everywhere, fast to explain (saves interview time).
  • Cons — latency up to interval + RTT; wasted requests; connection churn unless keep-alive.
  • When — updates every few seconds OK; short-lived wait windows; realtime not the crux.

Long polling — easy near-realtime

Client requests; server holds until data (or timeout) then responds; client immediately re-requests. Feels push-like on plain HTTP.

Long poll latency when two updates arrive close together.
High-frequency updates pay a reconnect tax — SSE/WS win here.
  • Pros — standard HTTP; easy; near-realtime for infrequent events.
  • Cons — per-message callback latency; hanging requests confuse timeouts/monitors; browser connection limits per domain.
  • When — payment status "tell me when done"; infrequent alerts; upgrade from simple poll with little infra change.

Server-Sent Events — efficient one-way

HTTP response with Content-Type: text/event-stream and chunked transfer. Server writes many data: frames on one connection. Browser EventSource auto-reconnects; Last-Event-ID fills gaps.

const es = new EventSource('/api/updates');
es.onmessage = (e) => updateUI(JSON.parse(e.data));
  • Pros — built into browsers; auto-reconnect; better than long poll for frequent pushes; still HTTP.
  • Cons — one-way only; some proxies buffer streams (opaque failure); connection limits; hanging-request monitoring.
  • When — live dashboards, AI token streaming (ChatGPT-style), notifications outbound-only.

WebSockets — full-duplex champion

HTTP upgrade to a persistent bidirectional channel. Opaque messages (JSON/Protobuf). Best when high-frequency reads and writes share one pipe (chat, typing, cursors, multiplayer).

Clients through L4 LB to WS gateway to stateless services.
Terminate WebSockets early in a stable gateway; keep business services deployable.
  • Pros — lowest overhead for frequent duplex; wide support.
  • Cons — stateful; LB/sticky complexity; deploy churn; reconnect + missed-message recovery; hotspot connections.
  • Infra — prefer L4 or WS-aware L7; "least connections" balancing; heartbeats for zombie detection.

WebRTC — peer-to-peer

Clients use signaling, STUN, and optional TURN before a direct P2P data path.
Signaling + STUN for discovery; TURN only when peers cannot punch through NAT.

Direct browser-to-browser media/data after signaling (often via WebSocket/SSE). NAT traversal: STUN (hole punching) and TURN (relay fallback). Signaling itself is a mini realtime system.

  • When — video/audio calls, screen share, some collab presence (Canva cursors) / CRDT-friendly P2P Docs-like cases.
  • Pros — low latency; lower server bandwidth.
  • Cons — complex; STUN/TURN ops; setup delay; still sync home to mothership for durability.

Hop 2: server-side push / pull

Updates flow to server then to client with two open questions.
Same two questions as hop 1/2 — now from the server's point of view.

Once clients hold connections on some machine, an event (new chat message) must reach that machine. Three patterns:

Users connected to different servers; question which server holds User C.
The discovery problem: User A is on Server 1 — where is User C's socket?
  • Pull via polling — store events in DB; client polls; source and consumer decoupled; not true push.
  • Push via consistent hashing — each user/doc owned by one server; route publishes to the owner.
  • Push via pub/sub — Redis/Kafka topics; thin endpoint servers subscribe and forward.

Hop 2A — DB pull

Writers insert messages; readers SELECT … WHERE ts > ?. Simple; high latency; easy to forget poll QPS load on the DB.

Hop 2B — Consistent-hash ownership

Hash ring before and after removing server n8.
Own heavy connection state on one server; remove a node and only its arc remaps.

Modulo user_id % N works until N changes (almost everyone remaps). Consistent hashing + virtual nodes minimizes moves. Coordination via ZooKeeper/etcd for membership. Clients connect randomly then redirect, or discover the owner.

User A redirected from Server 1 to Server 2 via Zookeeper membership.
Connect anywhere → membership lookup → redirect to the owner → exchange data.
Update server routes a message to Server 2 then to User A's WebSocket.
Publish path: find owning server, then map to the local socket.
  • When — Google Docs–style heavy in-memory doc state; expensive to rebuild on every machine.
  • Scale event — dual-publish to old+new owners while draining connections; then flip membership.
  • Vs pub/sub — if endpoints are thin forwarders, prefer pub/sub.

Hop 2C — Pub/Sub

Publisher to pubsub to endpoint servers to clients.
Default hop-2 for most chat-like systems — endpoints stay interchangeable.

Client hits any endpoint (least-connections LB) → endpoint subscribes to user:{id} (or room topic) → publishers write the topic → all subscribed endpoints forward on the local socket map.

  • Pros — easy horizontal scale of endpoints; state concentrated in pub/sub; <10ms typical hop.
  • Cons — pub/sub SPOF/bottleneck (shard Redis/Kafka); many-to-many links; weaker presence unless you track connects explicitly.
  • Interview — name Redis pub/sub or Kafka; shard by key; least-connections on WS tier.

When to use in interviews

ScenarioTypical pick
Chat / typing / presenceWebSocket + pub/sub
Live comments (huge fan-out)WS/SSE + hierarchical aggregation
Collaborative docsWS + hash ownership + OT/CRDT
Dashboards / metricsSSE or poll
AI token streamSSE
Video callWebRTC + signaling
Notification bell (seconds OK)Simple polling

Common deep dives

Connection failures & reconnect

Mobile networks die silently (zombie sockets). Heartbeats detect death. Track last sequence / Redis Stream ID; on reconnect, replay missed events. Exponential backoff + jitter to avoid reconnect storms after deploys.

Celebrity / mega fan-out

1 celebrity → millions of sockets. Don't write one message into a million personal queues synchronously. Cache once; hierarchical regional fan-out; batch; see Scaling writes.

Write processors aggregate into a root processor then fan out via broadcast nodes.
Live comments / celebrity likes: aggregate (e.g. last 1s) then hierarchical broadcast — not one push per event per viewer.

Ordering

For product interviews, funnel a room/auction/doc through one partition or owner and stamp order there. Vector clocks are deep infra — mention only if asked.

Collab conflicts

Getting bytes there fast ≠ correct merge. OT or CRDTs for Docs-like editing — separate from the transport choice.

In your interview

What to say out loud

"Realtime is two hops. For hop 1 I'll start with polling unless we need sub-second push — then SSE for one-way or WebSockets for duplex, with an L4 or WS gateway so the rest stays stateless. For hop 2 I'll use Redis/Kafka pub/sub unless each connection owns heavy state like a Docs session — then consistent-hash ownership with coordinated drain on scale. Clients resume with sequence IDs; heartbeats kill zombies; celebrities get hierarchical fan-out."

Realtime scenario board

Cost and performance levers

Interview Q&A by level

Practice saying these out loud for realtime updates. Interviewers grade clarity and judgment more than buzzwords.

Interview takeaway

Match depth to the bar: define → trade off → operate. Don't dump principal answers in an entry-level screen.

Wrapping up

Real-time systems pair a delivery protocol with a fan-out trigger. Start simple, escalate with evidence, and keep socket state from infecting your whole architecture. Continue with Common patterns, Networking essentials, Message queues, Kafka, Redis, and Consistent hashing.

← Lattice