Understand the building blocks / CHAPTER 24
Polling, long polling, WebSockets, and server-sent events
Choose a real-time transport from direction, update frequency, recovery, and operational constraints.
Builds on Forward and reverse proxies, Load balancing, System design building blocks.
- Compare polling, long polling, WebSockets, and server-sent events.
- Estimate idle polling load and persistent-connection demand.
- Design ordering, reconnect replay, and slow-consumer behavior.
01Choose by direction and useful freshness
A report takes two minutes to run and updates progress every five seconds. The browser sends start and cancel commands, but most communication is progress travelling from the server to the browser. Ask who sends what and how soon it must appear before choosing the transport, the mechanism carrying the messages.
Ordinary polling repeats a status request:
- The browser asks for progress every ten seconds.
- The server returns the current status, even if nothing changed.
- An update just after a poll waits nearly ten seconds for the next one; an update just before a poll waits almost none.
- Under uniformly timed updates, the interval adds about five seconds of average detection delay. Network and processing time add more.
Polling is often enough when that delay is acceptable, but empty requests still consume work.
Long polling changes the waiting location:
- The browser sends a status request.
- The server holds it until an update or timeout.
- The browser receives a response and sends the next request.
This avoids many repeated empty replies for sparse updates. Servers and proxies still retain waiting connection and request state. Efficient asynchronous handling need not dedicate an operating-system thread to each idle request; an implementation that does so can run out of threads.
02Compare the four mechanisms on one workload
For a persistent stream, compare message directions and operating costs.
- A WebSocket starts with a handshake, an opening exchange that establishes a channel for messages in both directions. Frequent player actions and game updates can justify that two-way channel.
- Server-sent events, or SSE, sends a server-to-browser text stream over HTTP. The browser’s
EventSourceAPI can reconnect and carry event identifiers. Start and cancel commands can use separate authenticated HTTP requests. - A received event identifier is not automatically a durable record that the application applied that event. Both transports need application recovery rules.
| Mechanism | How report progress moves | Cost to check |
|---|---|---|
| Poll every ten seconds | Repeated request and response, including unchanged status. | Empty requests and interval delay. |
| Long poll | Hold a request until progress or timeout, then repeat. | Waiting connection state and coordinated timeouts. |
| SSE | Send progress on one server-to-browser stream. | Open connections, flushing, and replay after reconnect. |
| WebSocket | Send progress and commands on a two-way channel. | Open connections, message rules, and recovery. |
Calculate load for 100,000 active viewers:
- Ten-second polling produces
100000 / 10 = 10000requests per second, assuming evenly spread polls and excluding retries. - A persistent design avoids those repeated cycles but retains roughly 100,000 client connections.
- Budget each connection’s buffers, authentication state, and reconnect bursts. Measure the platform rather than assuming either option is universally cheaper.
Test the public path. A proxy may buffer SSE, close idle streams, or need WebSocket-upgrade support. Define authentication expiry, request limits, draining, and reconnection during replacement. A direct connection to the application does not verify those intermediaries.
03Recover the application, not merely the connection
Give one report’s updates stable version numbers, such as 11, 12, and 13, and retain the history needed for replay. The client saves a cursor: the last version it has applied.
Trace an interrupted delivery:
- The server safely records version
12and sends it. - The browser receives it, but disconnects before saving its new applied cursor.
- It reconnects with saved cursor
11and asks for later retained events. - Version
12can arrive again. For progress, compare its version with the last applied version and avoid applying the same update twice. Save application state and the applied position together where a repeated effect would matter.
Opening the connection again does not recover history that no longer exists. If cursor 8 predates retained events starting at 12:
- Detect the missing interval rather than report replay success.
- Fetch an authorized current snapshot, for example report state at version
15. - Use that snapshot’s matching version as the new cursor.
- Resume after 15. Keep changes such as version
16available even if they occurred during the snapshot fetch, so the continuation has no new gap.
Connection byte order does not establish one application order across several producers or reconnects. Define the ordering scope required by the report.
A slow browser must not accumulate unlimited memory:
- For progress, combine replaceable intermediate percentages into the latest state if the product permits it.
- For a financial ledger, dropping transactions would be wrong; retain the required events or provide a precisely defined saved snapshot.
- Set a maximum queued-byte count per browser. If adding an event would exceed it, combine replaceable progress updates into the newest state or close that connection and let it resume from saved history. Do not silently drop the terminal result. Slowing intake or delivery when the consumer cannot keep up is backpressure.
SSE suits this mostly one-way report if the environment supports it. Polling may be simpler if its delay is acceptable. Whichever carries the bytes, permission, saved progress, replay, and duplicate handling make recovery correct.
Reconnect uses durable application position
Follow the numbered arrows
- Report history → Connection serviceemit retained events
- Connection service → Browsertransport can disconnect
- Browser → Reconnect requestresume with persisted position
- Reconnect request → Snapshot fallbackdetect history gap
- Snapshot fallback → Current stateread an authorized snapshot and its version
- Current state → Connection servicecontinue after the snapshot’s version
Trace the diagram in words
- The browser reconnects using its saved applied version, 8.
- The service compares that cursor with history beginning at 12 and detects a gap.
- It returns an authorized snapshot with a matching version.
- The stream resumes after that version, including changes made during the snapshot fetch.
DRAW. CALCULATE. EXPLAIN.
Choose and recover a report channel
20 minutes · guided practice
A report lasts 120 seconds and changes progress every five seconds. It has 60,000 active viewers.
- Calculate ten-second polling demand and average interval delay under uniform update timing.
- Compare with the connection demand of a one-way stream.
- A reconnect asks after version
8, but retained events begin at 12. Explain a correct recovery path.
Compare the worked solution
- Polling generates
60000 / 10 = 6000requests per second before retries, including requests when progress is unchanged. - The ten-second interval adds about five seconds of average detection delay under uniform timing, plus network and processing time.
- A one-way stream keeps roughly 60,000 connections and their bounded state instead. Measure that cost and the real proxy’s streaming behavior. SSE with separate start/cancel requests is reasonable for mostly one-way progress.
- Cursor 8 cannot be replayed completely from history beginning at 12. Detect the gap, fetch an authorized current snapshot and its matching version, then request events after that version.
- Retain changes made during the fetch so the continuation has no new gap. Combining intermediate percentages can fit the progress contract; dropping irreplaceable payment events would not.
The checkboxes record your own assessment. The worked solution gives you a way to check the reasoning.
RETRIEVE BEFORE YOU REVEAL
Keep the important ideas.
Say the answer aloud, then turn the card over.
CARD 01What should be compared before choosing polling or a persistent stream?
- Decide the required direction and update delay.
- Estimate repeated polling requests and their interval delay.
- Estimate persistent connections, buffers, and reconnect bursts.
- Choose the simplest option that meets the promise on the actual platform.
CARD 02When does SSE fit, and when is a WebSocket more useful?
- SSE carries text events from server to browser; separate HTTP requests can start or cancel work.
- WebSocket carries messages in both directions on its established channel.
Both require permission checks, saved state, and application recovery after disconnection.
CARD 03What makes reconnect correct?
- Save the last applied event position.
- Replay later stable event IDs without repeating their effects.
- If history expired, fetch a snapshot with a matching resume version.
- Retain changes during that fetch. At the per-browser queued-byte limit, combine replaceable progress or disconnect and resume; do not accumulate unlimited events.
CHECK THE REASONING
Can you explain the choice?
Answer every question, then finish for an immediate score and an explanation for each answer. Aim for 80%, then revisit any gaps.
CLOSE THE LOOP
Explain it without the page.
Summarise the mechanism, one trade-off, and one failure mode. Then mark this chapter complete.