WebSockets vs Server-Sent Events vs Polling
HTTP was designed for request-response, but many applications need the server to push updates to the browser: chat messages, stock prices, notifications. There are four approaches, each with different tradeoffs.
1. Polling (Short Polling)
// Client asks every N seconds: "Any new data?"
setInterval(async () => {
const res = await fetch("/api/messages");
const messages = await res.json();
updateUI(messages);
}, 5000); // every 5 secondsPros: Dead simple. Works everywhere. Cons: High latency (up to 5 seconds), wasted bandwidth (many empty responses).
2. Long Polling
async function waitForMessages() {
const res = await fetch("/api/messages"); // server holds the request open
const messages = await res.json();
if (messages.length > 0) updateUI(messages);
waitForMessages(); // immediately reconnect
}Pros: Lower latency than polling, simpler than WebSockets. Cons: Still creates a new connection per request, hard to scale, no multiplexing.
3. Server-Sent Events (SSE)
const source = new EventSource("/api/messages/stream");
source.onmessage = (event) => {
const data = JSON.parse(event.data);
updateUI(data);
};Pros: Single HTTP connection, automatic reconnection, built into browsers, text-based (human readable). Cons: Server-to-client only (no client-to-server), one event stream per connection, not supported in IE.
4. WebSockets
const ws = new WebSocket("wss://example.com/ws");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
updateUI(data);
};
ws.onopen = () => ws.send(JSON.stringify({ type: "subscribe", channel: "chat" }));Pros: Full-duplex (both directions), low latency, no HTTP overhead. Cons: More complex, no automatic reconnect, harder to proxy/load balance, binary protocol.
Comparison Table
| Feature | Polling | Long Polling | SSE | WebSockets |
|---|---|---|---|---|
| Direction | C ←→ S | C ←→ S | S → C only | C ←→ S |
| Latency | High | Medium | Low | Lowest |
| HTTP overhead | Per request | Per request | One connection | None after handshake |
| Browser support | All | All | Modern (not IE) | All modern |
| Server complexity | Simple | Medium | Medium | Complex |
| Load balancer | Easy | Easy | Hard (sticky sessions) | Hard (sticky sessions) |
When to Use Each
- Polling: When updates are infrequent and latency doesn't matter.
- Long polling: When you need low latency but can't use WebSockets (legacy browsers, restrictive proxies).
- SSE: When the server mainly pushes data (notifications, live feeds) and you want simple HTTP semantics.
- WebSockets: When you need real-time bidirectional communication (chat, multiplayer games, collaboration).