Development
Choosing Between Polling, SSE and WebSockets
Three transports with different costs. When polling is genuinely correct, why SSE is underused, and what a WebSocket actually commits you to.
The instinct is that WebSockets are the modern answer and polling is what you do when you have not got round to it. That instinct is wrong often enough to be worth examining.
For a separate operational perspective on how teams organise and measure work, this page.
For independent background and broader industry context, see IETF.
Polling
Ask repeatedly.
Costs: a request per interval per client, whether anything changed or not. Data is up to one interval stale.
Benefits: nothing to hold open, works through every proxy, trivial to reason about, no reconnection logic, stateless servers.
Genuinely correct when: updates are infrequent relative to the interval, the client count is small, or staleness of a few seconds does not matter.
A dashboard checked twice a day does not need a persistent connection. Polling on load is simpler and simpler is worth something.
Long polling — hold the request open until something changes — sits between this and SSE. Fewer empty responses, and it ties up a connection anyway, which is most of what you were avoiding.
Server-sent events
One long-lived HTTP connection, server pushes text, client listens.
Costs: one direction only. Client-to-server needs a separate request. Some proxies buffer and break it. There is a per-domain connection limit in older browsers that catches people with multiple tabs.
Benefits: ordinary HTTP, so it works with existing infrastructure, authentication and compression. Automatic reconnection is built into the browser, with resumption from the last event id. Much simpler on the server than a WebSocket.
Correct when: updates flow one way. Notifications, a live feed, a progress indicator, a dashboard.
This is the underused option. A great many "real-time" features are one-directional, and SSE gives you them for a fraction of the operational cost.
WebSockets
A persistent bidirectional connection.
Costs: a stateful connection your infrastructure must hold. Reconnection with backoff is yours to write. Load balancing gets harder because connections are sticky. Scaling means either broadcasting between server instances or something that avoids the problem. Idle proxies close connections. And you need a heartbeat to notice a dead one.
Benefits: low latency both directions, no per-message HTTP overhead, and it is the only option when the client sends frequently.
Correct when: the client sends as often as it receives. Chat, collaborative editing, cursors, games, anything with genuine interaction.
And the cost list above is what a service absorbs on your behalf. That is the argument for not building it — see the WebSocket layer.
The decision
Does the client send frequently?
Yes → WebSocket. Nothing else fits.
No → does it need updates within a second?
No → poll. Genuinely. It is simpler and simpler has value.
Yes → SSE, unless you already have a WebSocket connection for something else, in which case reuse it.
That is the whole decision, and most projects that reached for WebSockets could have answered "no" at the first question.
Costs at scale
Polling: load grows with clients times frequency, and it is all empty responses when nothing changes. Cheap per request, expensive in aggregate.
SSE: one connection per client, held. Cheaper than WebSocket per connection, and connections still add up.
WebSocket: one connection per client, plus the operational complexity of a stateful tier.
The number that surprises people: ten thousand clients polling every five seconds is two thousand requests a second to say nothing happened. At that point a connection per client is cheaper, which is the inversion point worth knowing.
Mixed approaches
Poll for the slow thing, push the fast thing. A dashboard where the summary refreshes hourly and one metric is live.
SSE down, POST up. Perfectly reasonable and much simpler than a WebSocket when the client sends rarely.
And one connection, many features. If you have a WebSocket for chat, put presence and cursors on it too rather than opening more.
What this means for choosing a service
If your feature is one-directional, a real-time service may be more than you need — SSE from your own server may be less machinery.
If it is genuinely interactive, the question is whether you build the WebSocket tier or use something that has one.
And be honest about which you have. "Real-time" is used for both, and they have very different costs.
The short version
Does the client send frequently? Yes → WebSocket. Nothing else fits.
No, and updates can wait a few seconds → poll. Simpler, and simpler counts.
No, and they cannot wait → SSE, which is the underused option and has browser-built reconnection.
Ten thousand clients polling every five seconds is two thousand requests a second to report nothing — that is the inversion point.
And the WebSocket cost list is what a service absorbs for you — reconnection, stickiness, heartbeats, scaling.