WebSockets & Real-Time
HTTP asks; real-time apps need the server to speak first. Four patterns, one decision table.
The Problem: HTTP Only Answers
HTTP is request/response — the server can never start a conversation. But chat, live dashboards, multiplayer games and notifications all need server push. Everything in this guide is a workaround for that one asymmetry, from “ask repeatedly” to “keep a genuine two-way pipe open”.
The Decision Table
| Pattern | How | Latency | Cost | Reach for it when |
|---|---|---|---|---|
| Polling | GET every n seconds | up to n | n× wasted requests | Data changes rarely; simplicity wins |
| Long polling | Server holds request until data | low | 1 connection per client, re-opened | WebSockets blocked; legacy infra |
| SSE | One HTTP response, kept open, server streams events | low | cheap; auto-reconnect built in | One-way push: feeds, tickers, notifications |
| WebSocket | Upgraded TCP socket, full duplex | lowest | stateful connections to manage | Two-way: chat, games, collaborative editing |
How the WebSocket Upgrade Works
A WebSocket starts life as an HTTP request carrying Upgrade: websocket. The server answers 101 Switching Protocols, and from that moment the TCP connection stops speaking HTTP — both sides exchange lightweight frames in either direction until someone closes.
GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== — server — HTTP/1.1 101 Switching Protocols Upgrade: websocket Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
const ws = new WebSocket("wss://example.com/chat"); ws.addEventListener("open", () => ws.send("hello")); ws.addEventListener("message", (e) => console.log(e.data)); ws.addEventListener("close", () => /* reconnect with backoff */ 0);
The Real Cost: Scaling Statefulness
Plain HTTP servers are stateless — any instance can serve any request. A WebSocket pins each client to one specific server for minutes or hours. Now: how does server A deliver a message to a user connected to server B? You need a pub/sub backbone (Redis, Kafka) between instances, sticky-aware load balancing, heartbeats to detect dead connections, and reconnect-with-backoff on the client.
Interview Questions
Polling vs long polling vs SSE vs WebSocket — 30 seconds.
Polling asks on a timer (simple, wasteful). Long polling holds the request until data exists (low latency, still per-message overhead). SSE keeps one HTTP response open for a one-way server stream. WebSocket upgrades to a raw full-duplex pipe — lowest latency, highest operational cost.
How does a WebSocket get past HTTP infrastructure?
It begins as a normal HTTP GET with Upgrade headers, so it traverses proxies and auth like any request; after 101 Switching Protocols the same TCP connection carries WebSocket frames instead of HTTP.
Two servers, one chat room — user A on server 1, user B on server 2. Deliver a message.
Servers subscribe to a shared pub/sub channel (e.g. Redis). Server 1 publishes A’s message; server 2, subscribed, receives it and pushes down B’s socket. The socket layer and the fan-out layer are separate systems.
Why choose SSE over WebSocket for a live dashboard?
The data flows one way. SSE rides plain HTTP: no protocol upgrade, native auto-reconnect with Last-Event-ID, works with existing LBs/auth/HTTP2. WebSocket buys duplex you don’t need at the price of stateful infrastructure.