Practice this topic in a realistic system design interview
Imagine a notifications feature where users should see new messages soon after they arrive, but WebSockets feel like more machinery than the product needs.
Short polling means asking the server every few seconds. It forces an awkward trade-off: ask often and most requests return nothing; ask slowly and updates feel delayed.
Long polling is a middle ground. The client sends a normal HTTP request. If there is no new data yet, the server waits before responding. It returns when new data arrives or when a timeout fires. As soon as the client receives a response, it sends the next request.
This chapter covers how long polling works, how it compares with short polling, SSE, WebSockets, and WebRTC, how to avoid missed events, what can go wrong at scale, and when long polling is a good fit.
Long polling is a way for the server to push updates using normal HTTP requests.
The client sends a request such as:
The after value tells the server the last event the client has already processed.
If newer events already exist, the server responds immediately. Otherwise, it holds the request until an event arrives or a timeout fires.
After every response, the client asks again with the latest event ID it has seen.
Long polling is not one permanent connection. It is a chain of normal HTTP requests, where each request may wait before returning.
Loading simulation...
Short polling checks on a fixed schedule. Long polling waits for data.
| Metric | Short Polling | Long Polling |
|---|---|---|
| Request pattern | Request every N seconds | Keep one pending request |
| Empty responses | Common | Still possible on timeout, but less frequent |
| Update delay | Up to the polling interval | Usually soon after data is available |
| Server work | Constant even when idle | Mostly tied to active clients and events |
| Complexity | Low | Moderate |
For example, 100,000 clients polling every 5 seconds creates about 20,000 requests per second even if there are no notifications.
Long polling removes much of that waste, but it creates a different scaling problem: many requests stay open at the same time. It is useful, but it is not free.
A long polling request has three phases.
The server should first check reliable storage for events newer than the client's cursor.
This step matters because events may have arrived while the client was reconnecting, while a previous request timed out, or while the user was offline.
If no data exists, the server waits. A production server should not spin in a loop and keep checking over and over. It should pause the request and resume it when an event arrives from an event bus, database notification, queue, or in-process signal.
The server responds with either new events or an empty response. The client updates its cursor and sends the next request.
Timeouts are normal. They prevent requests from being held forever and keep proxies, load balancers, and clients from thinking the connection is stuck.
A typical hold timeout is around 20-60 seconds, but the right value depends on your setup. Proxy and load balancer idle timeouts should be longer than the server's long polling timeout.
The easiest mistake in long polling is to treat each open request as the only source of truth.
There is always a gap between one response returning and the next request being sent.
The fix is simple: use a cursor.
Each event should have a stable, increasing ID or timestamp. The client includes the last processed ID in every request. The server always checks reliable storage before waiting. This makes reconnect gaps safe.
For many systems, an increasing event ID is better than a timestamp. Timestamps can collide, move backward across machines, or create confusing edge cases.
A long polling client needs to handle four things: data, empty timeouts, errors, and cancellation.
The client timeout in these examples is 35 seconds, slightly longer than a typical 30 second server hold timeout. The client should wait longer than the server. If the client gives up first, it can cancel healthy requests before the server has a chance to respond.
The server should not dedicate one operating system thread to every waiting request. With many clients, that model wastes memory and can hit thread or file descriptor limits.
Use an async or event-driven server model. Good fits include Node.js with async handlers, Go with lightweight goroutines, async Python frameworks, Java or Kotlin reactive servers, JVM virtual threads, and Nginx/OpenResty-style servers.
At a high level, the server flow looks like this:
The event store and the pub/sub bus serve different purposes. The event store prevents missed events during reconnects. The pub/sub bus wakes up waiting requests quickly.
Do not rely only on pub/sub for correctness. Pub/sub messages can be missed. If a server misses one, the next request must still be able to recover from storage.
Long polling is simple at the HTTP level, but production systems still need careful limits.
Every active client can hold one request open. That means you need enough file descriptors, memory, and load balancer capacity for many open requests at once.
Thread-per-request servers can struggle because idle long polls still occupy threads. Async servers are usually a better fit.
Proxies often have default idle timeouts. If your server holds a request for 30 seconds but a proxy closes idle connections after 15 seconds, clients will see failures even though the app is working.
Configure the proxy to outlast the server hold:
If a deployment, proxy restart, or network incident drops many clients at once, they may all reconnect at the same time.
Use jitter and backoff after errors. For normal empty timeout responses, reconnect immediately. For failures, spread clients out so they do not all retry at once.
Long polling should usually behave like at-least-once delivery. A client may receive an event, process it, and then fail before saving the cursor locally.
Design event handlers to be safe to retry. If the client sees the same event ID twice, it should ignore the duplicate.
If a client falls far behind, returning thousands of events in one response can create a huge response and slow the client down.
Use page limits:
N events per response.For state-like updates where old values are no longer useful, consider compacting the response so the client does not waste time replaying old states.
Long polling sits between simple polling and always-open connections.
| Technique | Direction | Best For | Trade-Off |
|---|---|---|---|
| Short polling | Client asks repeatedly | Rare updates where delay is acceptable | Wasted requests or higher delay |
| Long polling | Server holds one request | Infrequent server-to-client updates over HTTP | Open request per client |
| Server-Sent Events | Server to client | Continuous one-way event streams | One-way only; HTTP/1.1 limits browsers to 6 connections per origin |
| WebSockets | Client and server | Two-way low-delay messages | Stateful connections; more proxy and load-balancing care |
| WebRTC | Peer/media connection | Audio, video, screen sharing, peer data | More involved networking and media setup |
Long polling fits best when updates flow from the server to the client at a low or moderate rate, and when you want to stay close to normal HTTP. It works well when WebSockets are unnecessary or not reliably available, and when the client can reconnect after every response.
Other options fit other traffic shapes. If the client sends frequent messages, choose WebSockets. If the server produces a continuous one-way stream, consider SSE. If the product needs audio, video, or peer-to-peer data channels, use WebRTC. If freshness barely matters, short polling or a normal HTTP request is simpler.
Long polling uses normal HTTP, so standard API security still applies. Authenticate every request and authorize the user for the requested topic, room, or resource. Use HTTPS and rate limits. Validate query parameters and cursors, and avoid leaking whether another user's events exist.
Long polling keeps requests open longer, so also think about abuse. An attacker who opens many long polls can consume connection slots without sending much traffic. Use per-user and per-IP limits, and cap the number of open long polls per authenticated user.
Useful production metrics include:
These metrics tell you whether the system is healthy, whether clients are falling behind, and whether proxy or load balancer timeouts are fighting your application timeouts.
Long polling delivers near-real-time server updates without a permanent two-way connection. The server waits before responding, holding the request until data arrives or a timeout fires. The client then immediately reconnects with the latest cursor.
Cursors prevent missed events, so the server should always check reliable storage before waiting. Timeouts are normal because empty responses keep the request flow healthy.
Async, event-driven servers scale this better because they can handle many open requests without one thread per connection. Long polling fits moderate server-to-client updates. Two-way messaging is better served by WebSockets, and media or peer-to-peer data by WebRTC.
Its appeal is timely updates that stay inside plain HTTP, which for many systems is the right trade-off.
10 quizzes