Every post in this series so far has shared one assumption: the client asks, the server answers, the connection closes. That model breaks down the moment you need a chat message, a live score, or another user’s cursor to show up the instant it happens, not the next time someone thinks to ask. WebSockets fix this by turning the connection itself into something that just stays open — so the server can hand you data whenever it wants, not only when you request it.
The problem: how do you get updates without asking?
Before WebSockets existed, the only tool was HTTP, and HTTP only moves in one direction per exchange — client asks, server answers, done. The workaround was polling: have the browser ask “anything new?” every few seconds, forever, whether or not the answer has changed. It works, but almost every request comes back empty, and real-time starts to mean whatever your polling interval is, not actually real-time.
Polling
- Client repeatedly asks "anything new?" on a timer
- Most requests come back with nothing changed
- Update latency = however long you wait between polls
- A new HTTP request/response cycle, every single time
WebSocket
- One connection, opened once, left open
- Server sends the instant there is something to send
- Update latency ≈ network latency, not a polling interval
- Zero connection overhead after the handshake
Step one — the handshake that upgrades HTTP
A WebSocket connection is born as an ordinary HTTP request. The magic is in a few headers that ask the server to switch protocols on this same connection instead of responding normally.
It starts as a completely normal HTTP request — just with extra headers asking the server to switch protocols instead of returning a page.
Wait — is any of that encrypted?
No, and that trips people up. Sec-WebSocket-Key and Sec-WebSocket-Accept aren’t security — they’re a handshake ritual that stops a plain HTTP server (or a cache sitting in between) from accidentally treating a WebSocket upgrade as a normal request it doesn’t understand. Actual encryption comes from running the handshake over HTTPS, which upgrades it to wss:// instead of ws:// — the exact same relationship as http:// and https://.
Step two — now either side can just talk
This is the part that has no real equivalent in a request/response world. Once the socket is open, a message can originate from the server with nothing from the client prompting it — and in a chat room, a message from one client gets relayed to another through the server.
Client A sends a message over the already-open socket. No new request, no headers, no URL — just a frame of data.
101 Switching Protocols
Handshake status
Every ~30s
Typical heartbeat
As little as 2 bytes
Per-message overhead
Keeping the connection honest
An open socket can go quietly dead — a laptop sleeps, a phone switches networks, a corporate proxy silently drops idle connections — without either side getting a clean “closed” signal. The fix is a heartbeat: small ping/pong frames sent every 20–30 seconds. No pong back in time, and the server treats the connection as dead and cleans it up.
WebSocket vs. Server-Sent Events
If data only ever needs to flow server → client — a live feed, a progress bar, a notification stream — a full bidirectional WebSocket can be more than the job needs. Server-Sent Events (SSE) cover that narrower case over plain HTTP, with automatic reconnection built into the browser for free.
WebSocket
- True two-way — either side sends anytime
- Binary or text frames
- Needs its own reconnection logic
- Right fit: chat, multiplayer, collaborative editing
Server-Sent Events
- One-way — server to client only
- Plain text over a regular HTTP connection
- Browser reconnects automatically
- Right fit: notifications, live feeds, progress updates
Where you’ve already used this
- Chat and collaborative tools — messages, typing indicators, and live cursors (Google Docs, Figma) all ride on an open socket.
- Live data — stock tickers, sports scores, and multiplayer game state all need updates faster than any reasonable poll interval.
- Notifications — the little badge that updates without a page refresh is almost always a push over a persistent connection.