// Engineering Log
WebSockets, Long Polling, and SSE: how real-time data exchange works
Published on 2026-09-22
// Fast route
This article belongs to the topic Servers and infrastructure.
Chats, notifications, market quotes, collaborative editing, and neural network responses that appear as words — all of this requires the server to push data to the client immediately, without repeated requests. HTTP is originally designed differently: the client asks, the server replies. For real-time exchange over it, three approaches are used: Long Polling, Server-Sent Events (SSE) and WebSockets.
Long Polling
Long Polling is a technique, not a separate protocol. The client sends a regular HTTP request, and the server does not respond immediately but keeps the request open until data appears or a timeout expires. Upon receiving a response, the client immediately sends the next request.
Advantages:
- works wherever HTTP works: through any proxies, firewalls, and old browsers;
- does not require anything special on the server or the load balancer.
Disadvantages:
- each message requires a full HTTP request with headers;
- there is a gap between the response and the new request during which an event may be delayed;
- thousands of pending requests load the server if it handles each request with a separate process or thread.
Today Long Polling is used as a fallback option when other methods are unavailable.
Server-Sent Events (SSE)
SSE is a standard browser mechanism for one-way event delivery from server to client. The client opens a regular HTTP connection, the server responds with the type text/event-stream and does not close it, sending events as they occur.
The browser has a built-in EventSource object for this:
const events = new EventSource("/api/events");
events.onmessage = (e) => {
console.log("New event:", e.data);
};
events.addEventListener("order-status", (e) => {
console.log("Order status:", e.data);
});Advantages:
- ordinary HTTP: no separate protocol or special load balancer configuration needed;
- the browser automatically reconnects on disconnect;
- named events are supported.
Limitations:
- only from server to client; to send data to the server the client makes regular requests;
- text only;
- over HTTP/1.1 the browser keeps at most 6 concurrent connections per domain, and each open tab with SSE occupies one of them. Over HTTP/2 events use separate streams of a single connection, and this issue disappears.
SSE is a good choice for notifications, event feeds, progress indicators, and streaming neural network responses.
WebSockets
WebSocket (RFC 6455, 2011) is a separate protocol with two-way exchange over a single persistent connection.
The connection starts as a regular HTTP request with headers Upgrade: websocket and Sec-WebSocket-Key. The server responds with status 101 Switching Protocols, and then over the same TCP connection both sides exchange frames — text or binary. Addresses look like ws:// (port 80) and wss:// (port 443, with TLS). The protocol provides control frames ping and pong to check the connection.
Advantages:
- bidirectional exchange without new requests;
- minimal per-message overhead;
- binary data support.
Characteristics:
- the connection lives long, so proxies and load balancers must be configured not to drop it;
- the application must handle reconnection, delivery acknowledgment, and restoration of missed messages — the browser does not do this;
- each open connection consumes server resources, so a server designed for many concurrent connections is required for large numbers of clients.
WebSocket over HTTP/2
Originally WebSocket worked only over HTTP/1.1. RFC 8441 (September 2018) describes starting WebSocket inside a single HTTP/2 stream: the server announces support with the SETTINGS_ENABLE_CONNECT_PROTOCOL parameter, and the client opens a stream with the extended CONNECT method and the pseudo-header :protocol: websocket. This way a WebSocket connection and regular requests go over a single TCP connection. Whether this works in your stack depends on the browser, proxies, and application — by default most proxies still proxy WebSocket over HTTP/1.1.
Which to choose
| Task | Approach |
|---|---|
| Notifications, feeds, job progress, streaming server response | SSE |
| Chat, collaborative editing, games, trading terminals — frequent bidirectional data | WebSocket |
| Clients behind strict corporate proxies, old devices | Long Polling as a fallback |
| Data changes every few minutes | Regular periodic requests — simpler than the other options |
Many libraries (for example, Socket.IO) choose the best available transport themselves and fall back to Long Polling if WebSocket is unavailable.
Proxies and load balancers
Proxy settings are needed in two areas: forwarding the upgrade headers for WebSocket and timeouts for long connections.
- Nginx. The
UpgradeandConnectionheaders are not forwarded to the application automatically; they must be set explicitly; by default nginx closes a connection if there is no data for 60 seconds, and for SSE you need to disable response buffering. A working configuration with amapblock and troubleshooting is in the article “Proxy servers: Part 2 — Nginx”. - HAProxy. WebSocket is supported without additional modules, but the
timeout tunneldirective is required, otherwise connections are closed according to normal timeouts. An example is in the article “Proxy servers: Part 3 — HAProxy”. - Caddy. The
reverse_proxydirective proxies WebSocket without additional configuration, and responses with typetext/event-streamare sent to the client immediately, without buffering. On configuration reload WebSocket connections are closed by default; this behavior is changed by thestream_timeoutandstream_close_delayparameters.
Typical errors
- Connection drops exactly after one minute. The proxy timeout for inactive connections fired. Raise the timeout and send pings from the application.
- SSE events arrive in a batch at the end. The proxy is buffering the response. Disable buffering for that endpoint.
- WebSocket works locally but not behind the load balancer. The
UpgradeandConnectionheaders were not forwarded, or the load balancer is distributing a single client’s requests across multiple servers while the application stores state in memory. You need client affinity (sticky sessions) to a server or a shared state store. - Missed messages after reconnection. The protocol does not guarantee this — the application needs message identifiers and retransmission.
// Similar task
If you are dealing with something similar
This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.
Article topic
Servers and infrastructure
VPS, Linux, web stack, migrations, hosting, databases, and core operations.
Typical tasks behind this topic
- Move a site or service to a new server
- Set up Linux, Nginx, databases, and backups
- Figure out why the system behaves unstably
// Next step
If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.
Open services// Reviews
Related reviews
Thanks to Mikhail for his responsiveness. We spoke by phone; he explained how I could do it myself. This is my second time reaching out — everything’s great and prompt.
Thanks to Mikhail for his responsiveness. We had a call; he explained how I could do it myself. This is my second time contacting him; everything is great and prompt.
Consultation on Nginx Proxy Manager and Portainer
2025-02-25 · ★ 5/5
I want to express my deep gratitude to the specialist who set up SEO-friendly URLs for me on OpenCart. Configuring them turned out to be easy and simple, and I'm glad I finally found a professional who did everything well and without unnecessary complications. Before this I went through four specialists, and each time there were issues with the setup, but this person handled the task perfectly.
I want to express my great gratitude to the specialist who configured SEO-friendly URLs for me on OpenCart. Setting up the URLs turned out to be easy and simple, and I'm glad that I finally found a professional who did …
Excellent work — this isn't the first time I've used them; they find solutions to complex problems. I recommend.
Excellent work, this isn't my first time contacting them; they find solutions to complex problems. I recommend.
Excellent work! He completed the assigned task on time and without errors. It was a pleasure to work with him; I recommend him.
Great job! Completed the assigned task on time and without errors. It was a pleasure to work together, I recommend.
Excellent specialist — he delved into the problem, figured it out, and fixed it. I recommend him.
Excellent specialist, delved into the problem, figured it out, and fixed it. I recommend.
I needed to resolve an SSL certificate issue on a server where the certificate had been issued through Nginx Proxy Manager. Mikhail clarified all the details of my setup and requested access to assess the feasibility of solving the issue, since he hadn't worked with that service before. He quickly figured it out and fixed my problem. Perfect cooperation)
I needed to solve an issue with an SSL certificate on the server that was issued through Ngnix Proxy manager. Mikhail clarified all the details of how everything is set up for me, asked for access to assess the …
Diagnosing Nginx Proxy Manager in a Docker container and resolving the issue
2024-03-15 · ★ 5/5
// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related