Summary
Polling, Server-Sent Events, and WebSockets each trade connection state, directionality, and infrastructure cost differently. Short polling is the simplest fallback; SSE is HTTP-native one-way push; WebSockets give full-duplex at the cost of stateful servers and trickier load-balancing.
Jump to the interview angleTransport comparison
| Transport | Direction | Reconnect | Protocol | Best fit | |
|---|---|---|---|---|---|
| Short polling | Client → Server (request-driven) | None — new request each tick | Plain HTTP GET on timer | Any proxy, any CDN | |
| Long polling | Client → Server (request-driven) | New request on response | Plain HTTP, server blocks | Low-latency fallback when SSE blocked | |
| SSE (EventSource) | Server → Client only | Automatic + Last-Event-ID replay | HTTP/1.1 text/event-stream | Notifications, feeds, live dashboards | |
| WebSocket | Full-duplex (both directions) | Manual — you write backoff logic | HTTP 101 upgrade → WS frames | Chat, games, collaborative editing |
SSE with controlled backoff
Close EventSource on error and schedule reconnect manually so backoff delay stays predictable — the browser's built-in retry uses a fixed 3 s.
// Works in any browser; replace URL with your endpoint.
function connectSSE(url: string, onMessage: (data: string) => void) {
let es: EventSource;
let retryDelay = 1_000; // ms
function connect() {
es = new EventSource(url, { withCredentials: true });
es.addEventListener("message", (e) => {
retryDelay = 1_000; // reset on success
onMessage(e.data);
});
es.addEventListener("error", () => {
es.close();
// EventSource would auto-reconnect, but we want backoff control
setTimeout(connect, retryDelay);
retryDelay = Math.min(retryDelay * 2, 30_000);
});
}
connect();
return () => es.close(); // cleanup
}
// Server side (Node / Edge):
// res.setHeader("Content-Type", "text/event-stream");
// res.setHeader("Cache-Control", "no-cache");
// res.write(`data: ${JSON.stringify(payload)}\n\n`);Closing EventSource on error bypasses the browser's fixed 3 s retry; backoff doubles up to 30 s, preventing server floods.
Pick by directionality first
One-way server push → SSE. Both sides send → WebSocket. No persistent connection acceptable, or behind proxies that block upgrades → polling.
Interview angle
Lead with directionality, then connection cost, then infra constraints. Mention SSE is often overlooked despite being simpler than WebSockets for one-way push.
Soundbite: "SSE for one-way push behind HTTP; WebSocket when the client sends too."
Key terms
- EventSource
- Browser API for SSE: opens a persistent GET, fires `message` events, auto-reconnects with `Last-Event-ID`.
- WebSocket upgrade
- HTTP 101 handshake that switches a TCP connection to the WebSocket frame protocol.
- Long polling
- Server holds a request open until data is ready, reducing empty responses vs. fixed-interval polling.
- Sticky session
- Load-balancer rule routing one client to the same server node, needed for stateful WebSocket connections.
- Heartbeat / ping-pong
- Periodic frames sent to keep a TCP connection alive through idle-timeout proxies.