Difference Between LongPolling, WebSockets, and ServerSent Events
All three exist to defeat the same limitation: a browser cannot receive data it never asked for, because plain HTTP is strictly request-then-response and the server has no channel to speak first. Each technique cheats that constraint differently — long-polling keeps re-asking but lets the server stall the answer until it has news, Server-Sent Events (SSE) holds one HTTP response open forever and dribbles text down it, and WebSockets abandon HTTP mid-connection to open a raw bidirectional TCP pipe. So the real difference is who holds the connection open, in which direction bytes may flow, and how much overhead each delivered message carries — not the definitions the names suggest.
The mechanisms side by side
Ajax polling is the baseline: the client fires a full HTTP request on a timer (say every 1s). If nothing changed, the server returns an empty body — a wasted round-trip that still pays the full cost of TCP framing plus request and response headers.
Long-polling keeps the request shape identical but changes server behaviour: instead of answering immediately, the server parks the request (a "hanging GET") and replies only when data arrives or a timeout fires. The client re-issues a new request the instant it gets a response, so the server almost always has a waiting request to push the next event into. Latency drops to near-zero, but every single message still costs one complete HTTP request/response cycle.
SSE keeps one HTTP response open indefinitely with Content-Type: text/event-stream. The server never closes it; it writes newline-delimited data: frames as events occur. It is one-directional (server→client only) and text-only, but it rides ordinary HTTP, so proxies, gzip, cookies and auth headers all just work.
WebSocket starts as an HTTP request but asks the server to switch protocols. After a 101 Switching Protocols handshake the connection is no longer HTTP at all — it is a full-duplex TCP channel over which either side sends lightweight binary or text frames at any time, with only 2–14 bytes of framing per message.
Worked example: a live price ticker for 5 minutes
A dashboard shows one stock price. The price actually changes on average once every 30 seconds, but users want to see a change within ~1 second. We hold the tab open for 300 seconds (10 real updates). Assume HTTP/1.1 request+response headers cost roughly 700 bytes per round-trip, and each price payload is 148.20 = 6 bytes. Watch what each approach spends to deliver those same 10 updates.
| Approach | Round-trips in 300s | Bytes moved (approx) | Worst-case staleness |
|---|---|---|---|
| Ajax polling @ 1s | 300 requests (290 return nothing) | 300 × 706 ≈ 212 KB | up to 1s |
| Long-polling | 10 request/response cycles | 10 × 706 ≈ 7 KB | ≈ 0 (delivered on event) |
| SSE | 1 handshake, then 10 pushed frames | 706 + 10 × ~15 ≈ 0.85 KB | ≈ 0 |
| WebSocket | 1 handshake (101), then 10 frames | 706 + 10 × ~8 ≈ 0.79 KB | ≈ 0 |
Polling burns ~250× the bytes of SSE while still being up to a second stale. Long-polling fixes the staleness but re-pays the 706-byte header tax on every update. SSE and WebSocket collapse the per-message cost to almost nothing because the connection stays open — the difference between them here is negligible for a pure server→client feed, which is exactly why SSE is the right tool for this shape of problem.
The two protocol details that decide real designs
WebSocket handshake — the upgrade. The client sends an ordinary HTTP request whose headers ask to leave HTTP:
GET /feed HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13The server proves it understood the protocol by hashing the key: Sec-WebSocket-Accept = base64( SHA-1( key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ) ) and replies:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=After the 101, no more HTTP semantics apply — which is precisely why any proxy, load balancer, or API gateway in the path must explicitly understand the upgrade or it will kill the connection.
SSE — auto-reconnect and Last-Event-ID. SSE has resilience built into the browser. The wire format is just text:
retry: 3000
id: 42
data: 148.20
id: 43
data: 148.35
If the stream drops, the browser EventSource reconnects automatically after retry milliseconds and sends a Last-Event-ID: 43 header on the new request, so the server can resume exactly where it left off — no missed events, no client code. WebSocket gives you none of this: reconnection, backoff, and replay are entirely your job.
Comparison matrix
| Dimension | Ajax Polling | Long-Polling | SSE | WebSocket |
|---|---|---|---|---|
| Direction | client→server (pull) | client→server (pull) | server→client only | full duplex (both) |
| Transport | HTTP | HTTP (held) | HTTP (streamed) | TCP after 101 upgrade |
| Connection lifetime | new per poll | new per message | one long-lived | one long-lived |
| Per-message overhead | full headers | full headers | ~a few bytes | 2–14 byte frame |
| Payload types | any | any | UTF-8 text only | text or binary |
| Reconnection | n/a (stateless) | manual re-request | automatic + Last-Event-ID replay | build it yourself |
| Proxy / gateway friendliness | trivial | trivial | good (plain HTTP) | needs upgrade support + sticky routing |
| Freshness | polling interval | near-instant | near-instant | near-instant |
| Typical fit | rare, non-urgent updates | compatibility fallback | feeds, notifications, progress, LLM token streams | chat, games, collaborative editing, trading |
Pitfalls
- SSE dies behind buffering proxies. Any intermediary that buffers responses (some nginx configs, older CDNs) will hold your event frames until the buffer fills, silently defeating "real-time." Disable proxy buffering (e.g.
X-Accel-Buffering: no) and prefer HTTP/2. - The 6-connection cap. Over HTTP/1.1 a browser allows only ~6 concurrent connections per domain. Open several SSE streams across tabs and the user hangs with no error. HTTP/2 multiplexing removes the limit — this alone is a strong reason to run SSE over h2.
- WebSockets are invisible to your gateway. After the 101 the traffic is not HTTP, so path-based routing, WAF rules, request logging, and per-request auth stop applying. Load balancers need sticky sessions because a connection is pinned to one backend for its whole life.
- Long-polling exhausts server resources. Each held request occupies a connection (and, on thread-per-request servers, a thread) for its entire wait. Ten thousand idle clients = ten thousand parked requests. Always set a server-side timeout so parked requests recycle.
- Idle connections get reaped. Load balancers and NAT gateways silently drop connections idle for 30–60s. SSE needs periodic comment pings (
: keep-alive\n\n); WebSocket needs ping/pong frames — otherwise clients "go quiet" without ever firing an error. - WebSocket auth is a footgun. Browsers don’t let you set custom headers on the WS handshake, so bearer tokens often get smuggled in the query string (logged everywhere) or the first message. Plan authentication before you build.
When to use which — and when not to
Pick-one heuristic, in order:
- Only server→client, and text? (live feeds, notifications, build/job progress, dashboards, streaming LLM tokens) → SSE. Cheapest to operate, auto-reconnect and replay for free, rides normal HTTP infra.
- Need bidirectional, low-latency, or binary? (chat, multiplayer games, collaborative editors, live trading order entry) → WebSocket. It is the only option that lets the client speak instantly and cheaply too.
- Can’t deploy SSE/WS (a legacy proxy strips upgrades, or an ancient browser) → long-polling as a graceful fallback.
- Updates are rare and a second of staleness is fine? → plain polling. Don’t open a persistent connection you have to babysit for data that changes twice an hour.
Trade-offs against the nearest alternative
SSE vs WebSocket. Choose SSE when the flow is one-way: you gain automatic reconnection with Last-Event-ID replay, free gzip/auth/cookies, and zero special infrastructure. You pay with unidirectionality (client→server still needs a separate fetch), text-only payloads, and the HTTP/1.1 connection cap. Choose WebSocket when you need duplex or binary: you gain a true two-way pipe with tiny per-message framing; you pay with self-built reconnection/replay, gateway and load-balancer complexity (sticky sessions), and losing everything HTTP gave you for free.
Long-polling vs SSE. Long-polling gains universal compatibility — it is just HTTP, so it works through anything. It costs a full header round-trip per message plus reconnect latency jitter, and it ties up a server connection per waiting client. Reach for it only as a fallback when SSE or WebSocket genuinely can’t be deployed.
Choose SSE when the server does the talking and the payload is text; prefer WebSocket when the client must talk back with low latency or you need binary; fall back to long-polling when the network path forbids persistent connections; stay on plain polling when updates are infrequent and mild staleness is acceptable.
Takeaways
- The difference isn’t "what they are" — it’s connection lifetime, direction, and per-message overhead. Persistent connections (SSE, WS) crush the header tax that polling and long-polling keep re-paying.
- SSE is the default for one-way text streaming precisely because auto-reconnect +
Last-Event-IDreplay are built into the browser and it rides ordinary HTTP. - WebSocket buys you full-duplex and binary at the price of leaving HTTP behind — every proxy, gateway, and load balancer in the path must be in on it, and reconnection is your problem.
- Don’t reach for a persistent connection when polling would do; don’t force client→server traffic through SSE when the shape is really WebSocket.
Re-authored and deepened for this guide. Sources: MDN Web Docs on Server-Sent Events / EventSource and the WebSockets API; RFC 6455 (The WebSocket Protocol) for the handshake and Sec-WebSocket-Accept derivation; the WHATWG HTML Living Standard text/event-stream specification (retry, id, Last-Event-ID); and the original "Grokking the System Design Interview" descriptions of polling, long-polling, SSE, and WebSockets, corrected and extended with the comparison matrix, numeric worked example, and selection trade-offs.
🤖 Don't fully get this? Learn it with Claude
Stuck on Difference Between LongPolling, WebSockets, and ServerSent Events? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Difference Between LongPolling, WebSockets, and ServerSent Events** (System Design) and want to truly understand it. Explain Difference Between LongPolling, WebSockets, and ServerSent Events from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Difference Between LongPolling, WebSockets, and ServerSent Events** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Difference Between LongPolling, WebSockets, and ServerSent Events** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Difference Between LongPolling, WebSockets, and ServerSent Events** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.