System Design
Long Polling vs WebSockets
Two ways to get near-real-time updates to a browser - one a clever workaround over plain HTTP, the other a purpose-built two-way channel. They're often pitched as alternatives. Here's exactly when each wins.
When you need to push updates to a browser in something close to real time, two techniques come up again and again as the practical, general-purpose options: long polling and WebSockets. They're frequently framed as direct alternatives - and people often default to one or the other out of habit rather than careful fit. But they work very differently under the hood, and the right choice depends on what your feature actually needs.
This is the focused head-to-head: how each works, their concrete trade-offs, and a clear rule for choosing between exactly these two. (For the full landscape of real-time options - including polling, SSE, and webhooks - see the broader comparison guide; this one zooms in on the two that get pitted against each other most.)
How long polling works
Long polling is a clever technique that achieves near-real-time updates over ordinary HTTP, without any special protocol. Here's the mechanism:
- The client sends a request to the server, asking "do you have any updates?"
- Instead of responding immediately with "nothing," the server holds the request open - it waits, keeping the connection alive, until it actually has data to send (or a timeout is reached).
- When the server gets new data, it responds with it. The client receives the update.
- The instant the client gets that response, it immediately sends a new long-poll request, and the cycle repeats.
The trick is in step 2: by holding the request open until there's something to say, the server avoids the constant "nothing new" responses that plain polling suffers from, and the client gets updates promptly. It's request-response, but with the response deliberately delayed until there's real news.
How WebSockets work
WebSockets take a fundamentally different approach: they establish a single, persistent, two-way connection that stays open. After a one-time handshake (which starts as HTTP and upgrades), the connection becomes a full-duplex channel where both the client and server can send messages to each other at any time, instantly, until the connection closes.
There's no repeated request-response cycle. The connection is simply open, and either side pushes messages whenever it wants. (See the dedicated WebSockets guide for the handshake and connection details.)
graph TD
subgraph LP[Long Polling]
L1[Client requests] --> L2[Server holds open until data]
L2 --> L3[Server responds with data]
L3 --> L4[Client immediately re-requests]
L4 --> L2
end
subgraph WS[WebSockets]
W1[One handshake] --> W2[Persistent open channel]
W2 --> W3[Both sides push anytime]
W3 --> W2
end
This diagram contrasts the two. With long polling, the client requests, the server holds the connection open until it has data, then responds; the client immediately re-requests, repeating the cycle. With WebSockets, there's a single handshake, then a persistent open channel over which both sides push messages at any time, with no repeated request cycle.
The concrete differences
| Long Polling | WebSockets | |
|---|---|---|
| Connection | Repeated requests, each held open | One persistent connection |
| Direction | Server → client (per response) | Both directions, anytime |
| Protocol | Plain HTTP | Upgraded WebSocket protocol |
| Overhead per update | New request each time (headers, setup) | Minimal (message only) |
| Real-time quality | Near real-time | True real-time |
| Complexity | Simpler, works everywhere | More involved |
| Two-way interaction | Awkward (separate requests) | Native |
Let's translate that table into the differences that actually drive a decision.
Overhead. Long polling re-establishes a request after every response - each one carrying HTTP headers and connection setup. For frequent updates, this overhead adds up: lots of repeated round-trips. WebSockets pay the setup cost once (the handshake), then send messages with minimal overhead. For high-frequency, rapid exchanges, WebSockets are far more efficient.
Directionality. Long polling is fundamentally request-response - the server sends data when it responds to a poll. If the client needs to send data to the server, it does that as a separate request. This makes genuine two-way, interactive communication awkward. WebSockets are natively bidirectional - both sides push freely - which is exactly what interactive apps need.
Real-time quality. Long polling is near real-time: there's a small gap between receiving a response and re-establishing the next request, during which an update would wait. WebSockets are truly real-time: the channel is always open, so messages arrive the instant they're sent, in either direction.
Simplicity and compatibility. Long polling's advantage is that it's plain HTTP - it works through virtually any network, proxy, or firewall without special handling, and it's simpler to implement and reason about. WebSockets, while well-supported, occasionally face issues with proxies or networks that don't expect persistent upgraded connections, and they require more implementation effort (managing the persistent connection, reconnection logic).
When to choose which
Here's the rule, framed by what your feature needs:
Choose WebSockets when:
- You need true two-way, interactive communication (chat, multiplayer games, collaborative editing) - both sides constantly sending.
- Updates are frequent, so the per-message efficiency of a persistent connection matters.
- You need the lowest latency and genuine real-time responsiveness.
Choose long polling when:
- You need near-real-time updates but the interaction is mostly one-way (server pushing occasional updates to the client).
- Simplicity and broad compatibility matter more than peak efficiency - long polling works over plain HTTP everywhere, with less to build.
- You can't use WebSockets for some reason (infrastructure constraints, proxies that interfere), and need a reliable fallback.
Tip: A common real-world pattern is to use both together: try WebSockets first, and fall back to long polling if the WebSocket connection can't be established (some networks block them). Many real-time libraries do this automatically - preferring the efficient WebSocket and quietly degrading to long polling when needed, so the feature works everywhere while using the best available transport. You don't always have to choose one forever; you can prefer one and fall back to the other.
A worked example: building a notification feature both ways
To make the contrast concrete, imagine building a feature that shows a live count of new notifications.
With long polling: the client sends a request to /notifications/poll. The server doesn't respond immediately - it holds the request open, waiting. The moment a new notification arrives for that user, the server responds with the updated count. The client receives it, updates the badge, and immediately sends another /notifications/poll request, which the server again holds open. The count updates promptly when something happens; under the hood there's a continuous cycle of held-open requests, each a fresh HTTP request with its own headers and setup.
With WebSockets: the client opens a connection once, at page load, and it stays open. Whenever a new notification arrives, the server pushes a small message down the open connection, and the client updates the badge instantly. No cycle of re-requesting - one connection, server pushes whenever there's news.
For this feature - occasional, essentially one-way updates - long polling works fine and is simpler to deploy. But if the feature grows - mark-as-read synced live across devices, typing indicators, live chat - the interaction becomes frequent and two-way, and long polling's constant re-requesting becomes inefficient and awkward, while WebSockets' persistent two-way channel handles it cleanly. The right choice depends on where the feature sits, and where it's heading.
The resource cost: a closer look
The two consume server resources differently. Long polling holds a request open while waiting, tying up a connection for each wait, plus the churn of constantly establishing new requests after each response. At high frequency, the repeated setup (connection handling, headers parsed each time) adds meaningful overhead - lots of setup and teardown. WebSockets hold one connection open per client for the whole session, avoiding repeated setup - but the server maintains a large number of simultaneously open, long-lived connections, each consuming memory and state for as long as the user is connected.
So the trade: long polling has higher per-update overhead (repeated requests) but connections come and go; WebSockets have lower per-update overhead but require holding many connections open continuously. For frequent updates, WebSockets' efficiency usually wins. For infrequent updates across very many clients, the calculus is more nuanced. The key point is that both have a real cost at scale - neither is free - and the cost has a different shape.
Migration and coexistence
Many systems start with long polling (simpler, works everywhere) and migrate to WebSockets as their real-time needs grow - a feature that began as occasional one-way updates evolves into something interactive, and the team moves it when long polling's limits bite.
Because of this, the two often coexist. A robust setup frequently prefers WebSockets but falls back to long polling automatically when WebSockets can't connect (some corporate proxies or older infrastructure interfere with persistent upgraded connections). This gives the efficiency of WebSockets where available and the universal compatibility of long polling as a safety net. Many popular real-time libraries implement exactly this under the hood, so application code gets a real-time channel without caring which transport is in use. "Long polling vs WebSockets" need not be a permanent either/or - it can be "prefer one, fall back to the other."
Common mistakes
- Defaulting to WebSockets for one-way updates. If the server just pushes occasional updates to a passive client, WebSockets' two-way power is wasted and you've taken on persistent-connection complexity for no benefit. Long polling - or better, SSE - may be the simpler right answer.
- Defaulting to long polling for high-frequency interaction. A fast, two-way, chatty interaction makes long polling's repeated-request overhead and awkward bidirectionality inefficient and clumsy. That's WebSockets' territory.
- Ignoring fallback. Building exclusively on WebSockets without a fallback breaks the feature for users behind infrastructure that blocks them.
- Forgetting neither is free at scale. Both consume real server resources for their connections. Planning for the connection load - whichever you choose - is part of doing this right.
Choose by the interaction pattern (frequency and directionality) and by your scale and infrastructure, not by which technology sounds more modern.
Why long polling exists at all
It's worth understanding why long polling was invented, because it explains its character as a workaround. The web's request-response model fundamentally has no way for a server to initiate contact with a browser - the browser must ask first. For years, the only way to get server updates was plain polling: ask repeatedly on a timer. But plain polling is wasteful (most requests return nothing) and laggy (updates wait for the next poll). Long polling was the clever fix: keep the request open until there's actually something to send, eliminating the empty responses and the interval delay, while still using nothing but standard HTTP. It belongs to a family of techniques sometimes called "Comet" - HTTP-based methods for simulating server push before the web had real push.
This history frames long polling correctly: it's an ingenious workaround for a limitation of HTTP, not a purpose-built real-time channel. WebSockets, by contrast, were created specifically to remove that limitation - to give the web a real, persistent, two-way channel. So comparing them is comparing a clever adaptation of request-response against a protocol designed from scratch for real-time. That's why WebSockets are more efficient and capable for genuine real-time work, and why long polling endures mainly for its simplicity and universal compatibility - it works anywhere ordinary HTTP works, with no special protocol support required.
Performance at different scales
The right choice can shift with scale. At small scale - a few hundred or thousand concurrent users - both work fine, and long polling's simplicity may make it the pragmatic choice even for fairly interactive features; the overhead is negligible at that size. At large scale, the differences sharpen. For a high-frequency, interactive application with many users, long polling's constant request churn generates enormous overhead - every update means a full new request from every client - while WebSockets' persistent connections handle the same load far more efficiently. Conversely, for a very large number of clients receiving only occasional one-way updates, holding millions of persistent WebSocket connections open continuously may be more burdensome than long-poll requests that come and go.
The practical guidance: at small scale, optimize for simplicity (often long polling, or SSE for one-way); at large scale, optimize for the efficiency that matches your traffic pattern (WebSockets for frequent interactive traffic). And measure - the crossover point where one becomes clearly better depends on your specific update frequency, message sizes, and number of concurrent clients, so real systems often validate the choice with load testing rather than assuming.
A note on the bigger picture
It's worth remembering these two aren't the only options. If your need is purely one-way server-to-client streaming, Server-Sent Events are often a better fit than either - simpler than WebSockets, more efficient than long polling, with built-in reconnection. And for server-to-server notifications, webhooks are the tool, not these. The "long polling vs WebSockets" framing is common because they're the two general-purpose browser techniques, but always check whether a more specific tool fits your exact pattern before defaulting to either.
Interview: When a real-time feature comes up, being able to compare these two precisely is a strong signal. The senior move is choosing by the interaction pattern: "This is interactive and two-way, so WebSockets. If it were just occasional server-to-client updates, long polling would be simpler and sufficient - and I'd consider falling back to long polling if WebSockets are blocked." Showing you know long polling is a clever HTTP workaround while WebSockets are a purpose-built channel - and when each wins - demonstrates real understanding rather than defaulting to the trendier option.
The bottom line
Long polling and WebSockets both deliver near-real-time updates to a browser, but differently. Long polling is a clever workaround over plain HTTP - the server holds each request open until it has data, then the client immediately re-requests - making it simple, compatible everywhere, and good for occasional one-way updates, at the cost of per-request overhead and awkward two-way interaction. WebSockets establish one persistent, full-duplex connection, making them truly real-time and efficient for frequent, interactive, two-way communication, at the cost of more complexity.
Choose WebSockets for genuine interactive real-time; choose long polling for simplicity, compatibility, or as a fallback - and remember you can prefer one and fall back to the other. The decision is never about which technology is more impressive; it is always about how often and in which directions your data needs to flow. We cover real-time communication and its trade-offs across System Design Fundamentals.
Go deeper
- WebSockets API (MDN) - the persistent two-way channel in depth.
- Push technology (Wikipedia) - covers long polling and the family of push techniques.
- WebSocket (Wikipedia) - the protocol and how it compares to HTTP approaches.
- Comet (programming) (Wikipedia) - the history of long polling and related HTTP push techniques.