Polling vs long polling vs WebSockets: an interactive real-time simulator
To show users new messages as they happen, a server can be polled (asked every few seconds), long polled (asked, and the answer held back until there is one), or keep a connection open to push on: server-sent events one way, WebSockets both ways. They trade delivery delay, wasted requests and bandwidth against the cost of holding a connection open for every user.
The playground follows one user’s minute under each method, and adds up the whole fleet. Change how many users there are, how often each gets a message, and how often short polling asks.
100,000 connected users, each getting a message a minute on average. Short polling every 5 s delivers each message 2.5 s late on average and makes 20,000 requests a second, 92% of them answered with nothing. Long polling delivers at once, and its 4,218 requests a second are mostly answered with a message, though 61% still time out empty, but it holds 100,000 requests open. Server-sent events and WebSockets also hold 100,000 connections, and send each message with a few bytes of framing instead of HTTP headers: 377 KB/s against 16.3 MB/s for short polling.
- Delay, this minute
- 3.4 s
- Requests a second
- 20,000
- Answered empty
- 92%
- Held open
- 2,000
- Bandwidth
- 16.3 MB/s
- Delay, this minute
- 50 ms
- Requests a second
- 4,218
- Answered empty
- 61%
- Held open
- 100,000
- Bandwidth
- 3.7 MB/s
- Delay, this minute
- 50 ms
- Requests a second
- none
- Answered empty
- none
- Held open
- 100,000
- Bandwidth
- 387 KB/s
- Delay, this minute
- 50 ms
- Requests a second
- none
- Answered empty
- none
- Held open
- 100,000
- Bandwidth
- 377 KB/s
Short polling: simple, slow and wasteful
Asking every 5 seconds delivers a message 2.5 seconds late on average, and when messages are rare almost every answer is “nothing new”: with 100,000 users getting a message a minute, 20,000 requests a second, 92% of them empty, each with hundreds of bytes of headers. Polling faster cuts the delay and multiplies the waste. It is still the right choice when a few seconds’ delay is fine and the infrastructure must stay plain: a dashboard refreshing every 30 seconds.
Long polling: real time over plain HTTP
The client asks, and the server holds the request open until it has something or a timeout, typically 30 seconds, passes; then the client asks again. Messages arrive about as fast as with a socket, and it works through any proxy or firewall that allows HTTP. The costs: every message still pays for a full request, the server holds an open request per user, and a message sent while the client is reconnecting waits a round trip.
Server-sent events and WebSockets: one connection, pushed
Both keep one connection per user and push messages as they arrive, with a few bytes of framing instead of HTTP headers. Server-sent events are a long-lived HTTP response the server writes to: one direction only, text only, but the browser reconnects by itself and resumes from the last event id. WebSockets are a two-way channel for text or binary frames, the choice when the client also sends a lot, as in chat, games or collaborative editing, but reconnecting and resuming are left to your code.
| Short polling | Long polling | Server-sent events | WebSocket | |
|---|---|---|---|---|
| Delay | Half the interval | About a round trip | About a round trip | About a round trip |
| Direction | Client asks | Client asks | Server to client | Both ways |
| Cost per message | Requests, mostly empty | A request each | A few bytes | A few bytes |
| Held open | Nothing | A request per user | A connection per user | A connection per user |
| Reconnect | Not needed | Built in | Built in, resumes | Your code |
What holding connections costs
A million open connections is a million file descriptors, buffers and keepalive timers spread across your gateway fleet, and every deploy or crash drops them all at once and invites a reconnect storm, so clients must reconnect with jittered backoff. Load balancers must allow long-lived connections; sticky routing or a pub/sub layer is needed to reach the server that holds a given user’s connection. Mobile apps in the background cannot hold sockets at all, which is what push notifications are for.
The three in code
// server-sent events: the browser reconnects and resumes on its own
const events = new EventSource('/inbox/stream'); // sends Last-Event-ID on reconnect
events.onmessage = (e) => render(JSON.parse(e.data));
// WebSocket: two-way, but reconnecting and resuming are up to you
function connect(lastSeen) {
const ws = new WebSocket(`wss://chat.example.com/ws?since=${lastSeen}`);
ws.onmessage = (e) => { const m = JSON.parse(e.data); lastSeen = m.id; render(m); };
ws.onclose = () => setTimeout(() => connect(lastSeen), backoffWithJitter());
return ws;
}
// long polling: ask, wait up to 30 s, ask again
async function poll(since) {
for (;;) {
const res = await fetch(`/inbox?since=${since}&wait=30`); // the server holds it open
for (const m of await res.json()) { since = m.id; render(m); }
}
}In a system design interview
Pick by direction and scale, and say how messages reach the right connection: “Clients hold a WebSocket to a gateway tier. When a message is written, the chat service publishes it to the recipient’s channel in Redis pub/sub, and whichever gateway holds that user’s socket pushes it. Clients reconnect with backoff and jitter, passing the last message id so nothing is missed; offline users get a push notification instead.” Expect the follow-ups: how many connections one gateway holds, what happens on deploys, and presence.
Read the guide to WebSockets, SSE and long polling or presence and connection management, or watch a strong candidate design WhatsApp.
Questions people ask
What is the difference between polling and long polling?
With short polling the client asks the server for updates at a fixed interval, and most answers are empty when updates are rare, while updates wait up to a full interval. With long polling the server holds each request open until it has an update or a timeout passes, so updates arrive almost immediately and far fewer answers are empty.
When should you use WebSockets instead of long polling?
When messages flow often or in both directions, as in chat, multiplayer games or collaborative editing, and you can run infrastructure that holds long-lived connections. WebSockets avoid sending HTTP headers with every message. Long polling suits occasional updates through restrictive proxies, or as a fallback when WebSockets are blocked.
What is the difference between server-sent events and WebSockets?
Server-sent events are a one-way stream of text events from server to client over ordinary HTTP, with automatic reconnection and resumption from the last event id built into the browser. WebSockets are a two-way channel carrying text or binary frames, with reconnection left to the application. For notifications and feeds, SSE is often simpler.
How many WebSocket connections can a server hold?
Commonly tens of thousands to a few hundred thousand per machine, limited by memory for buffers, file descriptors and the work of keepalives and messages rather than by the protocol. Large systems spread millions of connections across a gateway tier and route messages to the right gateway through a pub/sub layer.
Why is short polling inefficient?
Every poll is a full HTTP request and response with hundreds of bytes of headers, whether or not anything has changed. When updates are rare, most polls return nothing, and the average delay is half the polling interval, so making it faster multiplies the wasted requests to buy lower latency.
How do clients avoid missing messages when a WebSocket reconnects?
Each message carries an id or sequence number; the client remembers the last one it processed and, on reconnecting, asks the server for everything after it, which the server reads from a store such as a message table or log. Server-sent events do this automatically with the Last-Event-ID header.
What happens to open connections during a deploy?
Restarting a gateway drops every connection it holds, and all those clients reconnect at once, which can overload the remaining gateways or the services behind them. Deploys drain connections gradually, and clients reconnect with exponential backoff and random jitter so the reconnections spread out.