Overview
HTTP is request-response, so a server cannot normally push data to a browser. Real-time features (chat, live scores, notifications, collaborative editing) use one of four techniques. Short polling asks repeatedly. Long polling holds each request open until there is data. Server-Sent Events (SSE) keep one HTTP response open and stream events from server to client. WebSockets upgrade the connection to a full-duplex channel where both sides can send at any time.
The choice depends on direction, frequency, and infrastructure. SSE is simple, works over plain HTTP, and reconnects automatically, but is one-way. WebSockets support bidirectional, low-latency messaging but need connection-aware load balancing and more careful scaling. Polling is simplest and fine when updates are rare.
Short polling is checking the mailbox every five minutes. Long polling is waiting at the door until the courier arrives. SSE is a courier who keeps delivering to your door as items arrive. WebSockets are a phone call where both of you can talk at any moment.
When to use it
- Chat, presence, typing indicators.
- Live dashboards, sports scores, stock tickers.
- Notifications and progress updates for long jobs.
- Collaborative editing and multiplayer games.
Where it shows up in interviews
Recognize it when: clients must see updates without refreshing.
- Design a chat application
- Design a live sports scoreboard
- Design a notification system
Recognize it when: millions of open connections.
- Design WhatsApp
- Design a collaborative document editor
Where it is used in real software
Use WebSocket gateways that keep persistent connections and fan out messages from backend services.
LLM responses are commonly streamed to browsers with Server-Sent Events.
Many products use SSE or long polling for notifications and build logs because it works through standard HTTP infrastructure.
Key terms
- Short polling
- Client requests updates at fixed intervals.
- Long polling
- Server holds the request until data is available or a timeout.
- Server-Sent Events
- One long HTTP response streaming text/event-stream messages to the client.
- WebSocket
- Full-duplex connection upgraded from HTTP.
- Fan-out
- Delivering one event to many connected clients.
How it works, step by step
- 1Pick direction and frequency
One-way updates suit SSE; two-way frequent messages suit WebSockets.
- 2Establish the connection
SSE is a normal GET; WebSocket starts with an HTTP Upgrade handshake.
- 3Route messages to the right connection
A pub/sub layer (Redis, Kafka, NATS) tells each gateway server which connected users need the event.
- 4Handle disconnects
Heartbeats, reconnect with backoff, and resume from the last event ID.
- 5Scale gateways
Many stateless-ish gateway servers, sticky or connection-aware load balancing, and connection limits per node.
STEP 1Short polling: GET /updates every 5 s. Simple, but most responses are empty and updates arrive up to 5 s late.
Comparison
Choose by use case
| Technique | Direction | Latency | Infrastructure | Good for |
|---|---|---|---|---|
| Short polling | Client pulls | Up to interval | Plain HTTP | Rare updates |
| Long polling | Server responds when ready | Low | Plain HTTP | Fallback for older environments |
| SSE | Server to client | Low | Plain HTTP (streaming) | Notifications, LLM streaming, feeds |
| WebSocket | Both ways | Lowest | Upgrade-aware proxies | Chat, games, collaboration |
NOWTechnique: Short polling | Direction: Client pulls | Latency: Up to interval | Infrastructure: Plain HTTP | Good for: Rare updates
Default to SSE for server push; use WebSockets when the client also sends frequent messages.
Implementation
// Server: stream events over one HTTP responseapp.get("/events", (req, res) => { res.set({ "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }); res.flushHeaders(); const send = (event: { id: string; type: string; data: unknown }) => res.write(`id: ${event.id}\nevent: ${event.type}\ndata: ${JSON.stringify(event.data)}\n\n`); const unsubscribe = notifications.subscribe(req.user.id, send); const heartbeat = setInterval(() => res.write(": ping\n\n"), 25_000); // keep proxies from closing req.on("close", () => { clearInterval(heartbeat); unsubscribe(); });}); // Browser: reconnects automatically and sends Last-Event-IDconst source = new EventSource("/events");source.addEventListener("order-shipped", (e) => console.log(JSON.parse((e as MessageEvent).data)));Complexity and performance
Memory and file descriptors are the limits.
vs full HTTP headers per poll.
Trade-offs
SSE is simpler, works with HTTP/2 and standard proxies, and auto-reconnects, but is server-to-client only and text-based; WebSockets are bidirectional and binary-capable but need upgrade-aware infrastructure.
Open connections make servers stateful; scaling needs connection-aware load balancing and a pub/sub layer to route messages to the right server.
Variants and related techniques
Newer HTTP/3-based transport with streams and datagrams.
APNs and FCM deliver to mobile devices even when the app is closed.
Common mistakes
- Holding all connections on one server.
Fix: Use many gateway servers plus pub/sub (Redis, NATS, Kafka) to fan out events.
- No heartbeat.
Fix: Idle connections are dropped by proxies; send periodic pings and detect dead peers.
- Losing events during reconnects.
Fix: Include event IDs and let clients resume from the last one.
Interview questions
When would you choose SSE over WebSockets?
When updates flow mainly from server to client, such as notifications, live feeds, or streaming LLM output. SSE uses plain HTTP, reconnects automatically, and is simpler to scale. Choose WebSockets when clients also send frequent low-latency messages.
How do you scale a chat system with millions of WebSocket connections?
Run many gateway servers that hold connections, register which user is on which gateway, publish messages through a pub/sub or messaging layer, and have gateways deliver to their local connections. Use heartbeats, connection limits, and graceful draining during deploys.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Build a live notification stream with SSE | Easy | Event format and reconnects. |
| Design a chat gateway for 10M connections | Hard | Fan-out and routing. |