WebSockets vs Server-Sent Events vs Long Polling
WebSockets vs SSE vs long polling: how each pushes data to clients, connection costs at scale, and how chat and live feeds use them.
Plain HTTP is request-response: the client asks, the server answers. Chat, live scores, notifications, collaborative editing and dashboards need the server to push data as soon as something happens. The three main techniques are long polling, server-sent events (SSE) and WebSockets.
Short polling (the baseline)
The client asks "anything new?" every few seconds. Simple, but wasteful: most responses are empty, and an update waits for the next poll, so latency is up to the full interval. Fine for data that changes rarely; poor for chat.
Long polling
The client sends a request and the server holds it open until there is new data (or a timeout of, say, 30 seconds), then responds. The client immediately sends the next request.
- Pros: works everywhere plain HTTP works, including old proxies; easy to add to a REST API.
- Cons: a new request per message adds headers and overhead; held requests tie up server resources; ordering and missed messages need a cursor (
after=42).
Server-sent events (SSE)
SSE is a standard for streaming text events from server to client over one long-lived HTTP response (Content-Type: text/event-stream). Browsers support it natively through EventSource, which reconnects automatically and resumes with the Last-Event-ID header.
id: 43
event: score
data: {"match": "IND-AUS", "runs": 287, "wickets": 6}
id: 44
event: score
data: {"match": "IND-AUS", "runs": 291, "wickets": 6}- Pros: plain HTTP (works with HTTP/2 multiplexing, proxies and load balancers), automatic reconnection and resumption, very simple.
- Cons: one direction only (client-to-server still uses normal requests) and text only.
WebSockets
A WebSocket starts as an HTTP request with Upgrade: websocket, then becomes a persistent, full-duplex connection carrying small framed messages both ways with very low overhead.
- Pros: true bidirectional, low-latency messaging, text or binary, minimal per-message overhead. The natural fit for chat, multiplayer games and collaborative editing.
- Cons: you handle reconnection, heartbeats and resumption yourself; some proxies and corporate networks interfere; long-lived stateful connections complicate load balancing and deploys.
Comparison
| Long polling | SSE | WebSockets | |
|---|---|---|---|
| Direction | Server → client (per request) | Server → client | Both ways |
| Connection | Repeated HTTP requests | One long HTTP response | One upgraded TCP connection |
| Latency | Low, plus a reconnect per message | Low | Lowest |
| Reconnection | Built into the loop | Automatic (EventSource) | Your code |
| Overhead per message | High (full HTTP request) | Low | Very low |
| Best for | Simple, infrequent updates; legacy environments | Feeds, notifications, live scores, AI token streaming | Chat, games, collaboration, trading |
Scaling persistent connections
Holding millions of connections changes the architecture. Connections are cheap individually (tens of KB of memory each with a tuned server) but they are stateful: a message for user B must reach the specific server holding B's connection.
- Separate connection gateways from business logic so you can deploy logic without dropping connections.
- Track presence: which gateway holds each user, with a TTL refreshed by heartbeats.
- Use pub/sub (Redis, Kafka, NATS) to deliver to the right gateway.
- Load balance with least connections, and on deploys drain gracefully: tell clients to reconnect elsewhere, with jittered backoff to avoid a reconnection storm.
- Persist messages first, push second, so a client that missed pushes can catch up with a cursor when it reconnects.
Where it’s used
Keep a persistent WebSocket (or similar) per client, with gateway fleets holding millions of connections and pub/sub fan-out behind them.
Stream generated tokens to the browser with server-sent events, since the stream is one-way and HTTP-friendly.
Push price and score updates over SSE or WebSockets to many read-only subscribers.
Use persistent bidirectional connections to exchange edits and cursor positions in real time.
In an interview
- Pick the simplest technique that fits: SSE for one-way feeds, WebSockets for two-way chat or games, long polling only for constraints like old proxies.
- Explain how a message finds the recipient's connection: presence registry plus pub/sub between gateways.
- Persist before pushing, and let reconnecting clients catch up from a cursor or last event ID.
- Address connection limits per server, heartbeats, and graceful draining on deploys.