5 min read

Q05 — What is long polling, and why did it exist before WebSockets?


Why did we need an alternative to regular polling at all?

Regular polling — where the client asks "any updates?" every few seconds — has an obvious problem: most of those requests return nothing. The client is burning network bandwidth, server CPU, and connection overhead just to hear "no" repeatedly.

More importantly, the latency is bounded below by the polling interval. If you poll every 5 seconds, a message could wait up to 5 seconds before the client finds out about it. For a chat app or live notification system, that's unacceptably slow.

But this was the world before WebSockets. HTTP/1.1 was the only option, and HTTP/1.1 only allows the client to initiate communication. The server cannot spontaneously push to the client. Engineers needed a way to fake server push using only the tools HTTP gave them.

Long polling was that solution.


What exactly is long polling?

The key insight of long polling is: what if the server just... doesn't answer right away?

In regular polling, the server answers immediately — even if the answer is "nothing new." In long polling, when the server receives a "anything new?" request and there's nothing to report, it holds onto the request instead of responding. It parks the connection and waits. When something actually happens — a new message arrives, a price changes, a job completes — the server responds with that data. If nothing happens within a timeout window (typically 30–60 seconds), it responds with "nothing" and the client immediately re-requests.

code
Client: anything new?
Server: [holds connection open... waiting...]
[30 seconds later — a new chat message arrives]
Server: yes, here it is → connection closes
Client: [immediately sends next request] anything new?
Server: [holds connection open... waiting...]

From the client's view, the request takes a long time — hence the name. From the user's view, messages feel instantaneous: the server responds the moment something happens, and the response reaches the client within a normal network round trip.


Why was this better than regular polling?

Two major improvements:

Latency drops to near-zero. The client's long-poll connection is already waiting at the server when the event happens. The server responds immediately. The only delay is network transit time — milliseconds, not polling interval seconds.

No wasted "nothing" responses. The server only responds when it has something to say (or the timeout expires). On a quiet channel, you might send one request every 60 seconds instead of one every 2 seconds. The load on the server is proportional to actual event volume, not polling frequency.


What are the real costs of long polling?

Long polling works, but it's fighting against HTTP's design, and the friction shows up in a few ways.

Server resource usage. Every waiting client holds an open HTTP connection. The server must track these parked requests — typically as file descriptors or async handlers. At 100,000 concurrent users, you have 100,000 open connections just sitting idle most of the time. This was a genuine engineering challenge in the early 2000s (the "C10k problem"), though async I/O made it tractable.

Constant reconnect overhead. Every time the server responds (either with data or with a timeout), the connection closes. The client immediately reconnects. That's a new TCP handshake for every event. On a chatty channel where messages arrive frequently, the connection is constantly being torn down and rebuilt. Each reconnect pays the handshake cost.

HTTP header overhead on every cycle. Each new long-poll request carries a full set of HTTP headers — Host, Cookie, Authorization, User-Agent — hundreds of bytes. These headers are the same on every request. The server responds with its own headers. All of this overhead is per-event, not per-session.

Proxy and timeout complexity. HTTP proxies and load balancers often have timeout settings that close idle connections. A long-poll connection that's been sitting open for 45 seconds might get cut off by a middlebox before the server can respond. Long polling applications had to carefully tune timeout values and handle proxy-closed connections gracefully.


Why did long polling persist for so long despite its costs?

Because it worked, and for years there was nothing better.

WebSockets weren't standardized until 2011. Before that, if you needed real-time behavior in a web browser, long polling was your best option. It powered Gmail's early chat feature, Facebook's notifications, and many other real-time web experiences throughout the 2000s.

Libraries like Comet (the general technique name) and tools like Bayeux/CometD abstracted the details, making long polling reasonably ergonomic to implement. Applications were designed around its limitations.

Once WebSockets arrived and browser support became widespread (around 2012–2014), most new real-time systems moved to WebSockets. Long polling became a fallback for environments where WebSockets couldn't be used — old browsers, strict proxies, or infrastructure that didn't support HTTP upgrades.


When is long polling still relevant today?

Long polling still makes sense in specific situations:

When the event rate is very low. If you're checking for occasional notifications that might arrive hours apart, a WebSocket connection sitting open for hours to deliver one message is wasteful. A long poll that reconnects only when needed may use fewer resources overall.

When WebSockets aren't available. Some corporate proxies or older API gateways don't support WebSocket upgrades. Long polling degrades gracefully through any HTTP-speaking proxy.

When simplicity matters more than efficiency. Long polling works over plain HTTP with no special server infrastructure. A WebSocket server requires persistent connection handling that some simple server frameworks don't support well.


The mental model

code
Regular polling:
  Client asks every N seconds → server answers immediately → N-second latency + wasted "no" responses

Long polling:
  Client asks → server holds connection → responds only when there's data → near-zero latency
  Cost: constant reconnect overhead, server holds connection state per client

Long polling is:
  ├── A hack that makes HTTP's request-response model simulate server push
  ├── Better than regular polling in latency and waste
  └── Worse than WebSockets in overhead and complexity

It existed because WebSockets didn't. It persists as a fallback where WebSockets can't be used.

Long polling is the engineering equivalent of making do with the tools you have. It was clever, widely deployed, and genuinely effective — until a better abstraction was invented.