When you build something that needs to feel "live" - a chat app, a live score, a self-updating dashboard-plain HTTP won't cut it. By default, the browser asks for something, the server answers it, and then the connection closes.
To make something that's real-time, you need to adopt one of three strategies:
-
Long polling
-
Server-Sent Events (SSE)
-
WebSockets
They all deliver live updates in significantly different ways-and demand different amounts of complexity, bandwidth, and server resources to pull off.
In this article, we cover the mechanism and costs of each one, so you can better decide which to use for what you're building.
Long Polling
The oldest trick of the three, long polling, still holds up as an effective option. It doesn't need anything special from the network in between the client and server, as the browser simply sends a normal request.
However, instead of the server answering right away, it holds the request open until it has something new to say, or until a set amount of time passes. The cycle repeats as soon as the browser gets an answer: it sends another request and waits again for the answer.
This is just plain HTTP traffic dressed up nicely to “feel” live, even though it technically isn’t. This means that traffic passes cleanly through infrastructure that the other two approaches might trip over. For example:
-
Corporate firewalls that only allow standard HTTP.
-
Older proxies and load balancers are unfamiliar with WebSocket.
-
CDNs or caching layers that are built for short request-response pairs.
The downside is that all this asking and answering adds up. Since every request starts from scratch, it adds a bit of lag each time. Multiply this by the number of users, and things can get expensive and slow quickly.
Knowing that, it’s still the best option if you need something that works on old or restrictive networks, only need infrequent updates, or you're adding real-time features to an existing system without rebuilding it.
Server-Sent Events
While long polling essentially fakes the real-time updates, SSE does it for real by having the browser open one connection using the EventSource API. The server then keeps it open, allowing it to send a steady stream of updates at any time. So unlike long polling, the browser doesn’t have to keep asking again and again. Reconnection also happens automatically if the connection drops.
The catch is that updates only go one way with SSE. The server can talk to the browser, but not the other way around. Another limitation, particularly on HTTP/1.1, is that most browsers only allow six of these open connections per website at a time. This can cause problems for users who open several tabs of your site at once. However, this limitation doesn’t exist on HTTP/2 or newer.
You should use SSE if the browser only needs to receive updates but never sends anything back. SSE also only carries UTF-8 text, so if you need to push binary data like images or audio, you'll have to encode it first or reach for WebSockets instead. For example: notifications, news feeds, or live scores. It's also the easiest to set up of the three and the least likely to cause problems.
WebSockets
WebSockets start by sending out a normal HTTP request, but then switch into a two-way connection, allowing both the server and the browser to talk to each other at any time. This makes it the best choice for any app with constant updates from both sides.
That power demands more resources as well, as you build your own reconnect logic, heartbeats to detect dead connections, and message framing. WebSocket traffic also doesn't always traverse older networks or strict firewalls as smoothly as standard HTTP, which is one reason why simple polling is still more common and, in fact, WebSocket adoption has leveled off.
While WebSockets are needed for heavy back-and-forth apps like chat apps, multiplayer games, and trading tools, plenty of teams also use WebSockets out of habit when SSE or polling would have sufficed.
Other Tips
It also helps to test your real-time layer against a real, imperfect network before launch, not just localhost. Latency and connection stability can vary by region, so simulating a distant client, for example, by learning how to get a US IP address if your servers sit elsewhere, is a practical way to catch reconnection bugs before real users hit them.
Test what happens when the connection drops, not just when it's slow. Real users lose connectivity constantly—WiFi switches, phones sleep, VPNs hiccup. Kill the connection mid-session before launch and check whether the client detects the drop, reconnects on its own, and doesn't lose or duplicate messages in the process. Though this mostly applies to WebSockets, since you have to write that reconnection logic yourself—SSE handles it automatically, and long polling just retries by nature.
Summary
To recap:
-
Use long polling when:
-
You need something that works everywhere.
-
Updates don’t need to be instant.
-
-
Use SSE when:
-
Only the server sends updates.
-
-
Use WebSockets when:
-
Both sides need updates from each other constantly.
-
The right choice will always depend on your needs and budget. Weigh trade-offs between simplicity, compatibility, and the performance demands of your app.