Webhooks vs. polling vs. long-polling vs. Server-Sent Events vs. WebSockets — when does each fit?
Five different answers to the same question — how does the client find out something changed — and interviewers use it to see whether you reach for WebSockets by habit or actually weigh the trade-offs.
LEARN BY DOINGPut your intuition to work3 steps
Webhooks vs. polling vs. long-polling vs. Server-Sent Events vs. WebSockets — when does each fit?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#The same question, five different answers
"How does the client find out something changed on the server?" This single question has five common answers, and interviewers use it specifically to see whether you reach for WebSockets out of habit or actually reason about the constraints: who initiates the exchange, whether a connection stays open, and who's supposed to be reachable.
#Polling — the client keeps asking
The client fires a request on a fixed interval and checks whether anything new came back.
It's the simplest thing that works: plain request/response, no special infrastructure, trivial to cache and rate-limit. The cost is baked into the interval — latency is bounded by how often you poll, and most of those requests come back with nothing new, which is pure waste multiplied by every idle client. Ten thousand clients polling every two seconds is five thousand requests per second doing nothing, all day, even when the system is quiet.
#Long polling — the client asks, the server waits to answer
The client sends a request; instead of answering immediately, the server holds it open until there's something to report or a timeout is hit, then responds — and the client immediately opens a new request.
This gets you near-real-time delivery without giving up plain HTTP/1.1 request/response semantics, so it survives old proxies and firewalls that a raw WebSocket handshake sometimes doesn't. The cost moves from "wasted requests" to "held-open connections" — the server needs a concurrency model (async I/O, not one thread per connection) that can hold thousands of pending requests without falling over, and there's a small gap between one response landing and the next request opening where an event could be missed if you're not careful about sequencing.
#Server-Sent Events — the server keeps talking
The client opens a single HTTP connection and the server streams events down it as text/event-stream, indefinitely, one direction only.
SSE is plain HTTP underneath — no special handshake, works through most infrastructure without configuration, and the browser's EventSource API handles reconnection and resumption (via Last-Event-ID) for you automatically, which is more than either polling or long polling gives you for free. Its real limitation is direction: the client cannot send data back over that same channel, only open it and listen. Over HTTP/1.1, browsers also cap open connections per origin (typically six), which used to matter for SSE-heavy pages — HTTP/2 removes that ceiling since it multiplexes streams over one connection.
#WebSockets — both sides talk, anytime
A WebSocket starts life as a normal HTTP request with an Upgrade: websocket header; once the server responds 101 Switching Protocols, the same TCP connection becomes a full-duplex, framed channel that either side can write to at any time.
This is the only option on this list where the client can push data at will, not just receive it — which is why it's the right fit for chat, collaborative editing (the kind of thing Yjs-based editors do), multiplayer games, and trading UIs. The bill comes due in operations: you own reconnect/backoff logic and heartbeats yourself, a WebSocket doesn't get ordinary HTTP caching or semantics, and fanning messages out across multiple server instances needs a shared backplane (Redis pub/sub, a message broker) since a message published on one instance has no way to reach a client connected to another instance without one.
#Webhooks — the producer calls you
All four options above put the client in the position of holding a connection or asking questions. A webhook flips that: when an event happens, the producer makes an outbound HTTP request to a URL the consumer registered ahead of time.
The consumer holds no connection open at all while idle — genuinely zero cost until an event fires — which is why this is the default for server-to-server integrations (Stripe, GitHub, and Slack all notify third parties this way). The trade is that the consumer must expose a publicly reachable HTTPS endpoint, delivery is at-least-once rather than exactly-once (the provider will retry on timeouts or errors, so the consumer must dedupe by event ID), ordering isn't guaranteed across retries, and anyone who discovers the URL could POST forged events unless the payload is signed (an HMAC signature header the consumer verifies before trusting anything in the body).
#Side by side
| Model | Who initiates | Connection | Latency | Idle cost at scale | Typical fit |
|---|---|---|---|---|---|
| Polling | Client | New request each cycle | Bounded by interval | High — constant requests from every idle client | Infrequent updates, simplicity over freshness |
| Long polling | Client | Held open until data or timeout | Near-real-time | Moderate — many pending connections | Notification inboxes, pre-WebSocket chat |
| SSE | Client (opens), server (pushes) | One long-lived, one-directional | Real-time | Moderate — one open connection per client | Live feeds, dashboards, notifications |
| WebSockets | Either side | One long-lived, full-duplex | Real-time | Moderate/high, depends on fan-out | Chat, collaborative editing, games, trading |
| Webhooks | Producer | None held — one request per event | Real-time-ish (delivery-dependent) | None while idle | Server-to-server integrations, async job completion |
#A decision framework, not a default
Start from who the consumer actually is. If it's another server, not a browser tab, a webhook usually beats making that server poll you. If it is a browser and the client only needs to receive updates, SSE gets you real-time delivery with automatic reconnection and none of the operational weight of a WebSocket fleet. Reach for WebSockets specifically when the client needs to send a continuous stream of data back, not just receive one. And when none of that infrastructure exists yet and updates are genuinely infrequent, polling is a legitimate, boring, reliable choice — the mistake isn't using polling, it's polling every two seconds for something that changes twice a day.
🧠 Check your understanding
0/4 · 0/4 answered1. An integration needs to notify a partner's server the instant a payment completes, and the partner's server is not a browser. What's the best fit?
2. A stock ticker dashboard in the browser only needs to receive price updates, never send data back. Which is the simplest fit that still gives near-real-time delivery?
3. Why can't a webhook consumer assume it will receive each event exactly once?
4. What operational cost is unique to WebSockets among the five models discussed?