When you open a chat app and a message appears instantly without refreshing the page, something interesting is happening under the hood. The browser isn't sitting there asking the server 'anything new?' over and over. A persistent connection is open, and the server pushes data the moment it's ready.
Understanding how real-time communication actually works - and the tradeoffs between approaches - will help you make better architecture decisions and avoid over-engineering features that don't need it.
The Problem: HTTP Is Request-Response
Standard HTTP is inherently one-directional: the client asks, the server answers, and the connection closes. This works perfectly for loading a webpage or fetching a list of users. But for real-time data, you need the server to be able to send data without the client asking first.
Three main approaches have emerged to solve this, each with different tradeoffs:
Approach 1 - Short Polling
The simplest solution: just keep asking. The client sends a request every N seconds to check if anything has changed.
When it works
Data that updates infrequently - a dashboard that refreshes every minute, a job status checker, a notification badge that doesn't need to be real-time.
The problem
If there's nothing new, you've made a wasted HTTP request. At 1 request every 3 seconds, that's 20 requests per minute, 1200 per hour - per user. At any real scale, this hammers your server with mostly-empty responses.
Approach 2 - Long Polling
A smarter version: the client sends a request, but the server holds it open until it has something to send (or a timeout is reached). The client immediately sends another request after receiving a response.
This reduces wasted requests significantly - the server only responds when there's actual data. But you're still creating a new HTTP connection every time a response is received, which adds overhead.
Approach 3 - Server-Sent Events (SSE)
SSE establishes a persistent one-way connection from server to client over a standard HTTP response. The connection stays open, and the server can push data any time.
SSE is underused. It's simpler than WebSockets, works over standard HTTP/2, handles reconnection automatically, and is perfect for anything that only needs server-to-client data flow: live feeds, notifications, progress updates.
Approach 4 - WebSockets
WebSockets open a full-duplex channel over a single TCP connection. Once established, both client and server can send messages at any time without the overhead of repeated HTTP handshakes.
WebSockets are the right tool when you need bidirectional, low-latency messaging: chat, multiplayer games, collaborative editing, live cursors, or trading platforms.
Which One Should You Use?
| Approach | Direction | Best For | Avoid When |
|---|---|---|---|
| Short Polling | Client → Server | Infrequent updates, simple setup | Data changes frequently |
| Long Polling | Server → Client | Moderate frequency, HTTP-only env | High volume, many concurrent users |
| SSE | Server → Client only | Notifications, live feeds, progress | You need client-to-server messages too |
| WebSockets | Bidirectional | Chat, games, collaborative tools | Simple one-way data streams |
A Common Mistake
Reaching for WebSockets for everything is one of the most frequent over-engineering mistakes in frontend development. If you're building a live notification bell or a streaming dashboard where only the server sends data, SSE is simpler, cheaper, and works better with HTTP/2 multiplexing - no WebSocket server infrastructure required.
Save WebSockets for the actual bidirectional use cases. Your ops team will thank you.
Quick Decision Guide
- Updates less than once per minute → short polling is fine
- Server pushes data, client only reads → use SSE
- Both sides send messages in real-time → use WebSockets
- Need to work in restrictive network environments → SSE or long-polling (both over HTTP)