System Design
Polling vs Long Polling vs SSE vs WebSockets vs Webhooks
Five ways to get data flowing between client and server in something like real time. They're constantly confused, and picking the wrong one means wasted resources or missed updates. Here's a clear decision guide.
The web was built on a simple model: the client asks, the server answers. That works perfectly for loading a page - but it breaks down the moment you want the server to tell the client that something happened. A new chat message, a stock price tick, a notification, a live score update: in all of these, the server has new information and the client needs to know, but the basic request-response model has no way for the server to speak first.
Over the years, several techniques emerged to solve this, each making a different trade-off. The five you'll encounter most are polling, long polling, Server-Sent Events, WebSockets, and webhooks. They're frequently confused, and choosing the wrong one wastes resources or misses updates. This is the decision guide: what each one is, how it works, and when to use it. (Each has its own deep-dive; this is the map that ties them together.)
The core problem: the server can't speak first
In the standard web model, communication is always client-initiated. The client sends a request, the server responds, and the connection closes. The server cannot, on its own, push new information to the client - it can only respond when asked. So how do you deliver server-side updates to a client in real time? Every technique here is a different answer to that question.
graph TD
A[Server has new data for the client] --> B{How does the client get it?}
B --> C[Ask repeatedly: Polling]
B --> D[Ask and wait: Long Polling]
B --> E[Server streams one-way: SSE]
B --> F[Two-way open channel: WebSockets]
B --> G[Server calls another server: Webhooks]
This diagram frames the central problem. The server has new data for the client, and the question is how the client gets it. The five answers branch out: polling means the client asks repeatedly, long polling means the client asks and waits, Server-Sent Events means the server streams one-way to the client, WebSockets means a two-way open channel, and webhooks means the server calls another server directly.
1. Polling: ask again and again
Polling is the simplest approach: the client repeatedly asks the server "anything new?" at regular intervals - every few seconds, say. The server responds each time, usually with "nothing new," until eventually there is something.
- How it works: the client sends a request on a timer, the server answers immediately (with new data or nothing), the client waits and asks again.
- Pros: dead simple, works with ordinary HTTP, no special infrastructure.
- Cons: wasteful. Most requests return "nothing new," burning bandwidth and server resources on empty checks. And there's latency - an update that arrives just after a poll waits until the next one. Polling more often reduces latency but multiplies the waste.
- Use when: updates are infrequent, slight delay is fine, and simplicity matters more than efficiency.
2. Long Polling: ask and wait
Long polling is a clever improvement. The client asks "anything new?" - but instead of answering "nothing" immediately, the server holds the request open until it actually has something to send (or a timeout passes). When the server responds, the client immediately opens a new long-poll request.
- How it works: the client requests, the server holds the connection until there's data, then responds; the client reconnects right away.
- Pros: much less wasteful than polling (no constant empty responses), and updates arrive promptly (the server responds the moment it has data). Works over standard HTTP.
- Cons: holding many open connections consumes server resources, and there's overhead in repeatedly re-establishing the connection after each response. It's a workaround, not a true push channel.
- Use when: you need near-real-time updates but can't or don't want to use newer push technologies; a common fallback.
3. Server-Sent Events (SSE): a one-way stream
Server-Sent Events open a single, long-lived connection over which the server streams updates to the client continuously. It's a true push channel, but one-directional - server to client only.
- How it works: the client opens an SSE connection once; the server then sends a stream of events over it whenever it has updates, without the client asking again. The browser automatically reconnects if the connection drops.
- Pros: efficient real-time server-to-client push over a single connection, built on standard HTTP, with automatic reconnection. Simple to use for one-way streams.
- Cons: one-way only (the client can't send data back over the same channel - it'd use a normal request for that). Designed for text-based event streams.
- Use when: the server needs to push a stream of updates to the client but the client doesn't need to send much back - live feeds, notifications, dashboards, stock tickers.
4. WebSockets: a two-way open channel
WebSockets establish a persistent, bidirectional connection between client and server. Once opened, either side can send messages to the other at any time, instantly, over the same connection - full duplex, real-time, both directions.
- How it works: the client and server perform a one-time "handshake" (starting as HTTP, then upgrading the connection), after which a persistent channel stays open. Both sides can push messages freely until the connection closes.
- Pros: true real-time, two-way communication with low latency and low per-message overhead (no repeated connection setup). The most powerful option for interactive real-time apps.
- Cons: more complex to implement and operate, requires maintaining persistent connections (which consume server resources at scale), and needs reconnection logic if a connection drops.
- Use when: you need genuine two-way real-time interaction - chat, multiplayer games, collaborative editing, live trading. (See the dedicated WebSockets deep-dive for how the handshake and connection work.)
5. Webhooks: server calls server
Webhooks are different from the others - they're about server-to-server communication, not browser-to-server. A webhook is a way for one server to notify another server when an event happens, by making an HTTP request to a URL the second server provided in advance.
- How it works: Server B registers a URL with Server A ("call this URL when X happens"). When X happens, Server A sends an HTTP request to that URL, pushing the event to Server B. It's a "reverse API call" - the provider calls you.
- Pros: efficient (no polling - the notification arrives exactly when the event happens), and the standard way services integrate and notify each other.
- Cons: the receiver must expose a public endpoint to receive the calls, handle retries if a delivery fails, and verify that incoming calls are authentic. It's for server-to-server, not for updating a browser directly.
- Use when: one backend service needs to notify another when something happens - payment confirmations, third-party integrations, event notifications between systems.
A worked example: choosing for three real features
Let me apply the decision guide to three concrete features, because seeing the reasoning is more useful than the table alone.
A live sports score page. The server has score updates; the client just needs to receive them as they happen. The client doesn't send anything back - it only watches. This is one-way, server-to-client streaming, so SSE is the clean fit: open one connection, stream score updates over it, done. WebSockets would work but waste their two-way capability; polling would be laggy and wasteful.
A chat application. Users send messages and receive them, constantly, with low latency, and it must feel instant. This is genuinely two-way and interactive, so WebSockets are the right call: an open channel where the client sends typed messages and the server pushes incoming ones, both directions, immediately.
A payment provider confirming a transaction to a merchant's backend. No browser is involved - one server needs to tell another "this payment succeeded." This is server-to-server, event-driven, so webhooks: the merchant registered a URL, and the provider calls it when the payment completes.
Three features, three different techniques, each chosen by the shape of the communication - direction, who initiates, and whether a browser is even involved. That's the decision in action.
How these techniques evolved
It helps to see these as a progression, because they emerged in roughly this order to solve each other's limitations. Polling came first - the obvious way to simulate real-time over a request-response web, but wasteful. Long polling improved it by holding the request open, cutting the wasted empty responses. Then SSE and WebSockets arrived as proper push technologies built into the modern web: SSE for efficient one-way streaming, WebSockets for full two-way communication - both eliminating the workaround nature of polling. Webhooks developed in parallel to solve a different problem: efficient server-to-server event notification without one server constantly polling another's API.
Seeing the progression clarifies why each exists. Polling and long polling are, in a sense, clever workarounds from before the web had real push; SSE and WebSockets are the real solutions; webhooks are the server-to-server answer.
Scaling real-time: the connection challenge
A consideration that unites SSE and WebSockets: they both rely on persistent connections, and persistent connections are expensive at scale. Each open connection is a resource the server must hold - memory, a file descriptor, state. Serving a million concurrent real-time users means holding a million open connections, a genuine infrastructure challenge that ordinary request-response systems (where connections are brief) don't face.
This shapes real-world design. Systems with massive real-time fan-out use specialized infrastructure to manage huge numbers of connections, load-balance them carefully, and often dedicate separate connection-handling layers. It's also a reason not to reach for persistent-connection techniques when you don't need them - if updates are infrequent, the cost of holding open connections may outweigh occasional polling. The persistent-connection cost is the hidden price of real-time, and accounting for it is part of designing these systems well.
Combining and falling back
Real systems often use several of these together and degrade gracefully between them. A common pattern: prefer the best technique but fall back - try WebSockets, and if they're unavailable (some networks or proxies block them), drop to long polling so the feature still works, just less efficiently. Many real-time libraries do exactly this automatically, attempting WebSockets first and quietly falling back, giving you the best available transport without the application caring which is in use.
It's also common to use different techniques for different parts of one application - WebSockets for a live editing channel (two-way), SSE for a one-way notification feed, webhooks for backend integrations - each doing the job it's best at. Don't think of these five as competing choices where you pick one for the whole app; think of them as a toolkit, where each communication need gets the technique that fits it, with graceful fallbacks where robustness matters. The landscape also keeps evolving (modern protocol improvements have shifted some of the original performance calculus), but the fundamental questions remain: which direction does data flow, who initiates, how real-time must it be, and is a browser involved?
The decision guide
Here's how to choose, framed by what you actually need:
| Technique | Direction | Real-time? | Best for |
|---|---|---|---|
| Polling | Client asks repeatedly | No (interval delay) | Infrequent updates, simplicity |
| Long Polling | Client asks, server holds | Near real-time | Real-time without newer tech |
| SSE | Server → client stream | Yes (one-way) | Live feeds, notifications, dashboards |
| WebSockets | Both directions | Yes (two-way) | Chat, games, collaboration, trading |
| Webhooks | Server → server | Yes (event-driven) | Backend-to-backend notifications |
The quick logic:
- Do you need browser updates or server-to-server? Server-to-server → webhooks. Browser → one of the others.
- One-way or two-way? If the client needs to send data back constantly → WebSockets. If it just needs to receive a stream → SSE.
- Can't use push technologies? Fall back to long polling (efficient) or polling (simplest).
Interview: Real-time features come up often in system design ("design a chat app," "design live notifications"), and knowing these options precisely is a strong signal. The senior move is matching the technique to the actual need: "Chat is bidirectional and interactive, so WebSockets. A live notification feed is one-way server-to-client, so SSE is simpler and sufficient. Payment confirmations between our backend and the provider are server-to-server, so webhooks." Defaulting everything to WebSockets - or to polling - when a lighter or more fitting option exists is exactly what distinguishes a memorized answer from real understanding.
Webhooks in practice: the details that matter
Because webhooks are server-to-server and fire automatically, a few details matter for using them reliably. Security: since anyone who knows your webhook URL could send fake events to it, the sender typically signs each webhook (with a shared secret) so the receiver can verify the call genuinely came from the expected source - verifying that signature is essential. Reliability: networks fail, so senders usually retry failed deliveries (the receiver was down, or returned an error), which means the receiver may get the same event more than once and should be idempotent - the same at-least-once reality message queues have. Acknowledgment: the receiver should respond quickly (often just a 200 status) to confirm receipt, and do any slow processing afterward, so the sender doesn't time out and retry unnecessarily.
It's also worth noting that webhooks put a requirement on the receiver the browser-based techniques don't: the receiver must expose a publicly reachable endpoint for the sender to call. That's fine for server-to-server integration but is exactly why webhooks aren't an option for pushing to a browser - a user's browser has no public URL to receive a call. This is the clearest line between webhooks and the other four: webhooks connect servers, while polling, SSE, and WebSockets connect a browser to a server.
The bottom line
All five techniques solve the same core problem - getting data to flow in something like real time when the basic request-response model can't push. Polling asks repeatedly (simple, wasteful). Long polling asks and waits (efficient near-real-time fallback). SSE streams one-way from server to client (great for feeds). WebSockets open a two-way channel (best for interactive apps). Webhooks let one server notify another (server-to-server events). The right choice comes down to direction (one-way, two-way, or server-to-server) and how real-time you truly need to be.
Match the technique to the actual communication pattern and you avoid both wasted resources and missed updates. We cover real-time communication and how to design for it across System Design Fundamentals.
Go deeper
- WebSockets API (MDN) - the two-way real-time channel in depth.
- Server-sent events (MDN) - the one-way server-to-client stream.
- Push technology (Wikipedia) - the broader category these techniques belong to.
- WebSocket (Wikipedia) - the protocol and how it relates to HTTP.