Webhook vs WebSocket vs SSE: which real-time option to use
Webhooks push events from one server to another with a single HTTP POST; WebSockets keep a two-way connection open, and server-sent events (SSE) stream one way from server to browser. Without HTTP/2, browsers allow only 6 SSE connections per domain; WebSockets use ports 80 and 443.
Webhooks push an event from one server to another with a one-off HTTP POST, while a WebSocket keeps one connection open so a server and a client, usually a browser, can send messages both ways at any time. Server-sent events (SSE) are the one-way middle ground, a long-lived HTTP response the browser reads as a stream, and long polling is the old fallback. Below is a comparison table of all four, followed by SSE vs WebSocket, webhook vs WebSocket, webhook vs SSE, and where long polling still fits.
Webhooks, WebSockets, SSE and long polling compared
The first question to settle is who needs the update: another server, or a person looking at a screen.
In practice, these often work together rather than as rivals, since a typical setup has a webhook from Stripe or GitHub land on your backend, which then pushes the news out to open browser tabs over SSE or a WebSocket.
| Webhooks | WebSockets | Server-sent events | Long polling | |
|---|---|---|---|---|
| Direction | Server to server | Both ways | Server to browser | Server to client, one response at a time |
| Who connects | The sender, once per event | The client, once (HTTP Upgrade, then 101) | The browser, with EventSource | The client, again after every response |
| Connection | A new HTTP POST per event | One long-lived TCP connection | One long-lived HTTP response | Requests held open until there is news |
| Data | JSON or form body plus headers | Text or binary frames | UTF-8 text, text/event-stream | Any HTTP response |
| When the link fails | The sender may retry (Stripe for up to 3 days) | You write the reconnect logic | Browser reconnects and sends Last-Event-ID | Client sends the next request |
| Limit to know | Answer fast: Slack 3 seconds, GitHub 10 | No backpressure in the browser API | 6 connections per browser and domain without HTTP/2 | Full HTTP headers on every message |
SSE vs WebSocket: one-way stream or two-way channel
When you're weighing SSE vs WebSocket, look at whether the client needs to talk back. With SSE, the browser opens the stream using new EventSource(url), and your server responds with status 200 and Content-Type set to text/event-stream, then keeps writing events made of event, data, id, and retry lines, with each event ending in a blank line. Event streams are always UTF-8. If the connection drops, the browser reconnects on its own and sends a Last-Event-ID header so the server can resume where it left off, and to keep old proxies from dropping an idle connection, the HTML standard suggests sending a comment line starting with a colon about every 15 seconds. Without HTTP/2, browsers allow only 6 open SSE connections per browser and domain across all open tabs, though over HTTP/2 that limit is negotiated between server and client and defaults to 100 streams.
A WebSocket (RFC 6455, December 2011) starts as a single HTTP request that upgrades to a two-way connection (ws:// on port 80 or wss:// over TLS on port 443) carrying text and binary frames along with ping and pong control frames. You have to write reconnection logic yourself, and the browser WebSocket API doesn't support backpressure, so if messages arrive faster than your app can process them, it can buffer them in memory or stop responding.
As a rule of thumb, pick SSE for feeds, notifications, and progress updates, and use WebSockets for chat, games, and collaborative editing where the client talks back a lot.
SSE response (example)
HTTP/1.1 200 OK
Content-Type: text/event-stream
id: 7
event: build
data: {"status":"passed"}
: keep-alive
WebSocket handshake (RFC 6455, trimmed)
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Webhook vs WebSocket
The difference in webhook vs WebSocket comes down to one-off requests between servers versus an open session with a client. A webhook sends one HTTPS request per event from a provider to your server, which must be reachable from the public internet and return a 2xx status within a few seconds (GitHub gives you 10 seconds, Shopify gives 5, Slack gives 3) or the delivery counts as failed and the provider may retry it later. Nothing stays connected between events.
A WebSocket is a session where the client dials out once and both sides talk over that same connection for as long as it stays open, which fits a browser or mobile app that can't accept incoming connections. Use webhooks for payment, repository, and order events between backends, and a WebSocket or SSE for a live dashboard or chat in a browser. A browser tab can't receive a webhook on its own because it doesn't have a public URL, so your backend has to receive the webhook first and forward it.
Webhook vs SSE
When comparing webhook vs SSE, you're looking at the same push idea built for two different audiences. A webhook makes one HTTP request per event to a server, while SSE holds one HTTP response open to a browser and carries many events over it.
Recovery works differently too: a webhook sender decides whether and when to retry a failed delivery, whereas an SSE client reconnects on its own and passes Last-Event-ID to pick up missed events. If a provider only sends webhooks, receive them on your backend and stream them to the browser over SSE.
Where long polling still fits
Under RFC 6202 (April 2011), HTTP long polling works by having the client send a request that the server holds open until an event happens or a timeout hits, at which point the server sends a complete response and the client immediately sends a new request. Every response is a full HTTP message with all its headers, and while the average delay is close to one network transit, the worst case is over three network transits (long poll response, next request, second response).
The RFC notes a default browser timeout of 300 seconds and successful experiments up to 120 seconds, though 30 seconds is generally a safer server value. Use long polling only where SSE and WebSockets are blocked.
Watch webhooks arrive in your browser
If you want to watch incoming webhooks the way you'd watch a live feed, a free bin on webhooks.sh handles the receiving-server part for you. Create a bin at view.webhooks.page or run curl -X POST https://webhooks.sh/v1/bins, point your provider at the ingest URL or test it with curl, and every request shows up live in your browser with its method, path, headers, and body.
A free bin lasts 48 hours, takes up to 100 requests per day with bodies up to 100KB, and displays the latest 10 requests in the viewer. You can claim the bin with a free Google sign-in before it expires to keep the same URL and hold onto new requests for 30 days. When you're ready to forward events to code running on your own machine, read our guide on how to test webhooks locally.
# 1. Create a free bin (or open view.webhooks.page)
curl -X POST https://webhooks.sh/v1/bins
# 2. Send it a webhook the way a provider would
curl -X POST https://<bin>.webhooks.page/build \
-H "Content-Type: application/json" \
-d '{"event":"build.finished","status":"passed"}'
FAQ
Is a webhook the same as a WebSocket?
No. A webhook is a single HTTP POST sent per event from one server to another, while a WebSocket is a long-lived, two-way connection that's usually opened by a browser or app.
Should I use SSE or WebSockets?
Use SSE if only the server needs to send updates like feeds, notifications, or progress, especially since SSE reconnects on its own. Pick WebSockets if the client talks back often, such as in chat or games.
Can a browser receive a webhook?
Not directly, because receiving a webhook requires a public URL that the sender can reach. You have to receive the webhook on your server and push the update to the browser over SSE or a WebSocket.
Does SSE work over HTTP/2?
Yes. Running SSE over HTTP/2 removes the old limit of 6 open connections per browser and domain, and the stream limit is negotiated between the server and client with a default of 100.
Is long polling worse than WebSockets?
For frequent messages, yes, because every response carries full HTTP headers and the worst-case delay is over three network transits. Keep long polling as a fallback for networks that block WebSockets and SSE.
When should I use webhooks instead of WebSockets?
Use webhooks when an update goes from one server to another and you run an HTTPS endpoint that can accept incoming requests, such as for payment, repository, or order events.
Last updated
Try it in 10 seconds.
Create a free bin at view.webhooks.page — no signup, no install. Point your sender at the URL and watch requests land live. Bins expire after 48 hours.