LESSON 4.4
Polling, SSE and WebSockets
The four ways to get fresh data to a client, what each costs at scale, and how to choose without over-engineering.
6 min read
Plain HTTP is request and response: the client asks, the server answers. But chat messages, live scores, notifications and collaborative edits start on the server. How does the server tell the client something happened? There are four standard answers, from simplest to most capable.
Polling
The client asks every few seconds: "anything new?"
It is simple, stateless and works everywhere. The cost is waste: most requests return nothing, and freshness is limited by the interval. 1 million clients polling every 5 seconds is 200,000 requests a second, mostly empty. Polling is the right answer when updates are rare or a little delay is fine.
Long polling
The client asks, and the server holds the request open until there is news or a timeout of 30 seconds or so passes. As soon as the client gets a response, it asks again.
Updates arrive almost immediately and empty responses become rare. It still uses ordinary HTTP, so it works through restrictive proxies. The cost is many open requests on the server and a new request after every message.
Server-Sent Events (SSE)
The client opens one HTTP request and the server streams events down it as they happen, as plain text lines. Browsers reconnect automatically and resume from the last event ID.
SSE is one-way, server to client. For many "live" features that is all you need: notifications, live feeds, progress updates, AI responses streaming in word by word. The client sends anything else with normal requests.
WebSockets
A WebSocket starts as an HTTP request, then upgrades to a persistent, two-way channel. Either side can send messages at any time with very little overhead.
This is the tool for genuinely interactive features: chat, multiplayer games, collaborative editors, where the client sends frequent small messages too.
Polling
- Simplest
- Stateless servers
- Cacheable
- Wasted requests
- Delay up to the interval
Pick it when: Infrequent updates, minute-level freshness.
Long polling
- Near-real-time over plain HTTP
- Many held requests
- Reconnect after each message
Pick it when: Real-time needed but WebSockets are blocked.
SSE
- Simple one-way stream
- Auto-reconnect with resume
- Server to client only
Pick it when: Feeds, notifications, progress, streaming text.
WebSockets
The scaling problem with persistent connections
SSE and WebSockets keep a connection open to one specific server. That changes how you scale:
- Connection limits. One server might hold 50,000 to 500,000 idle connections, depending on memory and tuning. A million online users means a fleet of connection servers.
- Routing messages. When user A sends a chat message to user B, the server holding B's connection must get it. Two common answers: a registry that maps users to servers, or a pub/sub layer (Redis Pub/Sub, Kafka) that every connection server subscribes to.
- Deploys and failures. When a connection server restarts, its clients all reconnect at once. Clients should back off with jitter, and the system must be able to replay missed messages.
Module 12 returns to real-time updates in depth: fan-out, presence and delivery guarantees. For now, the rule is to pick the simplest mechanism whose freshness and direction match the requirement.
Try it
Chat Service HLD
Design a chat service, the classic case for persistent two-way connections.