Part I β The Pipes Β· Lesson 2.4
Web Sockets
In one lineOne HTTP request upgrades into a persistent two-way pipe that stays open for the session.
Where you've seen itWhatsApp Web β the "typingβ¦" indicator only works because the browser can send without being asked.
Diagram
THE UPGRADE β starts as HTTP, then stops being HTTP
Client Server
β β
βββ GET /ws HTTP/1.1 ββββββββββββββββΊβ
β Upgrade: websocket β
β Connection: Upgrade β
β Sec-WebSocket-Key: dGhlIHNh... β
β β
βββ 101 Switching Protocols βββββββββββ β not 200
β Sec-WebSocket-Accept: s3pPLM... β
β β
ββββββββββ ws:// frames, both ways ββββ‘
βββββ {type:"typing"} ββββββββββββββββΊβ
βββββ {type:"message"} ββββββββββββββββ
βββββ {type:"presence"} βββββββββββββββ
βββββ ping βββββββββββββββββββββββββββΊβ keepaliveCONNECTION STATE MACHINE β the part interviews actually ask about
[connecting] ββopenβββΊ [open] ββclose/errorβββΊ [reconnecting]
β² β β
β β send() β backoff
β βΌ β 1s,2s,4s,8sβ¦
β queue if not open β
βββββββββββββββββββββββββββββββββββββββββββββββββ
on success: replay queue, resubscribe,
fetch missed messages by cursorHow it works
- Client opens
new WebSocket(url); the browser sends an HTTP Upgrade request. - Server replies
101; the TCP connection is now a framed, full-duplex channel. - Either side sends messages at any time β text or binary, no headers per message.
- Heartbeats (
ping/pong) detect dead connections that TCP hasn't noticed. - On drop, reconnect with exponential backoff + jitter, then re-authenticate, re-subscribe, and fetch what you missed.
socket.onclose = () => {
delay = Math.min(delay * 2, 30_000) + Math.random() * 1000;
setTimeout(connect, delay); // never reconnect in a tight loop
};Trade-offs
| Use when | Avoid when |
|---|---|
| Both sides send, often | Only the server has news β SSE |
| Sub-second latency is the feature | Updates are minutes apart β poll |
| Chat, cursors, games, live collab | You need HTTP caching or CDN |
What you now own: authentication (the handshake carries cookies, not Authorization headers β use a ticket), sticky sessions or a pub/sub backplane (Redis) so any server can reach any client, per-connection memory limits, and message ordering after reconnect.
Interview angle
"Your chat works locally and breaks behind the company proxy. Why?"
- Some proxies strip the
Upgradeheader or kill idle connections;wss://(TLS) survives far more of them. - Add heartbeats so a silently dead connection is detected, and always ship an SSE or long-poll fallback.
- Behind a load balancer, a reconnect can land on a different server β you need a shared pub/sub layer, not in-memory state.
Recap
- One handshake, then a permanent duplex pipe with tiny per-message overhead.
- The protocol is the easy part; reconnect, resubscribe, and replay are the design.
- Only pay for duplex when the client genuinely needs to talk back.