Blueprint
Realtime & messaging

WebSockets, SSE & polling

HTTP only speaks when spoken to. Three ways to push data the other way — and the scoring is on picking the simplest one that works, not the fanciest.

01

What it is

HTTP is request/response: the client asks, the server answers, the connection is done. The moment a design needs the server to initiate — a new chat message, a driver location, a live score — you need one of three escapes. Long polling holds a request open until data arrives, then the client immediately re-asks. SSE (server-sent events) streams a one-way text/event-stream down a single long-lived HTTP response. WebSockets upgrade the connection to a persistent full-duplex TCP channel where both sides push at will.

This decision is mandatory in chat, live comments, collaborative editors, driver tracking and notifications — and interviewers specifically watch whether you reach for WebSockets reflexively. Saying 'WebSockets' for a notification feed that updates twice an hour is a worse answer than plain polling, because WebSockets make every layer of your infrastructure stateful.

Say this out loud

My decision rule: client-to-server only means plain HTTP, server-to-client only means SSE, true two-way high-frequency traffic means WebSockets, and anything slower than about thirty seconds between updates means I poll and keep the whole system stateless.

02

The picture

long polling client server request → held until data → respond → repeat server-sent events client server one http response, events stream down · auto-reconnect websocket client server one upgraded tcp socket, both directions, stateful
three ways to get data to a browser: polling asks again and again, sse holds one downstream pipe open, websocket keeps one socket talking both ways.
03

The variants and when to pick each

Long polling — the fallback that works everywhere

The client sends a request the server parks until there's data or a timeout (30–60 s is typical), responds, and the client immediately re-requests. No special infrastructure, no proxy problems, works on everything built since 1999.

The costs are a latency gap between responses while the client reconnects, repeated header overhead on every cycle, and a server that holds thousands of idle open requests. I name it as the fallback for clients behind hostile corporate proxies, not as the primary transport.

Trade-offMaximum compatibility bought with the worst latency of the three and a request storm you re-pay every hold-timeout.

SSE — the underrated default for one-way feeds

One ordinary HTTP response that never ends, streaming events server-to-client. Auto-reconnect is built into the browser API, and Last-Event-ID lets the client resume from where it dropped — you get replay-on-reconnect without writing any of it. It passes through most proxies and CDNs because it is plain HTTP. This is how LLM token streaming works, and it is my answer for notifications, tickers and dashboards.

Limits: strictly server-to-client, text only, and HTTP/1.1 browsers cap at about 6 concurrent connections per domain — HTTP/2 multiplexing removes that ceiling, which is worth saying.

Trade-offYou give up the return channel — any client-to-server traffic goes over separate ordinary requests, which is fine for feeds and disqualifying for chat.

WebSockets — pay the state tax only when you need duplex

Lowest latency, bidirectional, binary-capable — the right call for chat, multiplayer games, collaborative editing and trading. But the connection is stateful, which breaks the stateless horizontal-scaling model everything else in the design relies on: the load balancer must be L4 or sticky, dead peers are only detected by heartbeat ping-pong (~30 s), and clients need reconnect-with-backoff logic.

The follow-up everyone gets: user A is connected to gateway 1, user B to gateway 7 — how does a message cross? A connection registry (Redis: user → gateway) plus pub/sub between gateways, or consistent-hash users to gateways so the sender can compute the target. Say this unprompted; it is the difference between knowing the API and knowing the system.

Trade-offSub-100 ms push latency in exchange for stateful infrastructure: sticky routing, heartbeats, reconnect logic and a registry that every message delivery now depends on.

Scaling the gateway tier — the numbers that size it

A tuned server holds 100k to 1M concurrent WebSocket connections (WhatsApp famously ran 1–2M per box on Erlang). Per-connection memory is roughly 10–50 KB, so 1M connections is tens of GB of RAM — connection count, not CPU, is usually the binding constraint. For 10M concurrent users I'd say ~20 gateway boxes at 500k each with headroom, and make the gateways dumb: terminate sockets, authenticate, forward — all logic lives in stateless services behind them.

On a silent connection death (mobile network drops without a FIN), the heartbeat catches it within a cycle, the client reconnects with jittered backoff, and per-conversation sequence numbers let it request everything it missed. Resumability is the part candidates forget.

Trade-offDumb gateways scale beautifully but push every hard problem — presence, ordering, delivery receipts — into the services behind them, where at least it's stateless.
04

Numbers worth memorising

Concurrent WebSockets per tuned box~100k–1M (WhatsApp: 1–2M on Erlang)
Memory per connection~10–50 KB → 1M conns ≈ tens of GB
Heartbeat interval / long-poll hold~30 s / 30–60 s
Push latencyWebSocket <100 ms; polling = poll interval
SSE per-domain limit (HTTP/1.1)~6 connections — fixed by HTTP/2
05

Where the interviewer pushes

The push is scale: "10M concurrent users — how many boxes, and how does server A reach a user on server B?" Do the arithmetic out loud — 10M ÷ 500k per box ≈ 20 gateways, doubled for headroom — then give the cross-server answer: registry in Redis mapping user to gateway, pub/sub for delivery, and sequence numbers so reconnecting clients can backfill. If you drew WebSockets but can't route across gateways, the interviewer concludes you've only used the browser API.

Second push: "why WebSockets here?" — usually asked when SSE or polling would do. The strong answer is to concede when it's true: notifications are one-way and infrequent, so SSE (or even 30 s polling) keeps every tier stateless and I'd only upgrade to WebSockets if the product later needs typing indicators or read receipts. Defending an over-engineered choice costs more than correcting it.

Shows up in

Found a bug or want more?

Tell me what's broken, missing, or wrong. Every message lands in my inbox.