Live score push
Design a service that pushes live sports scores to millions of people watching the same match at the same time. A score update should reach everyone within a second or two.
Where’s the slack?
Delivery: 1–2 seconds. Connection setup: seconds. Reconnect: seconds.A second or two of slack, bounded by something outside your system: the person in the next room shouting at their television.
The physical world sets this delivery budget, not engineering taste. If a neighbour with a TV feed shouts before your app updates, the product has failed in a way users notice viscerally. Broadcast feeds themselves run several seconds behind live, which gives you a little room, but not much. Call it one to two seconds end to end.
That is more slack than it first appears, and it is worth spending on purpose. It means you do not need microsecond delivery, you can batch updates into small windows, and you can accept a message taking a couple of hundred milliseconds to traverse a fan-out layer.
Connection setup has seconds of slack. A short pause when the app opens is fine. This matters more than it sounds, because it is what lets you stagger reconnections after a deploy instead of accepting a million simultaneous handshakes.
Historical data, statistics and commentary have minutes of slack and should be plain cached HTTP requests, not pushed. Mixing them into the live path is an easy way to over-build this design.
So: One to two seconds means you can batch updates into ~250 ms windows, which cuts fan-out work dramatically for a delay too short to notice. It also means the live channel should carry only what is actually live. Everything else is a cacheable request.
Work it through
Five stages, gated. You write your answer for each stage before its model answer unlocks. That is the core of the method.
Reference material for this problem. The diagrams below are here to check your own against once you have drawn it, not to read first.
The lifecycle
The numbers
There is no ingestion problem here at all. So the hard part is burst fan-out and holding ten million mostly-idle connections — including the moment they all reconnect at once.
The architecture
The mechanism
The decision this turns on
- —Every message is idempotent — a duplicate changes nothing.
- —A correction just works; the next message overwrites the wrong value.
- —Catch-up after a disconnect is simply "fetch current state" — no replay log.
- —Slightly larger messages, which at 300 bytes is irrelevant.
- —Smallest possible payload.
- —One missed message and the client is permanently wrong, silently.
- —Corrections need an explicit undo message and ordering guarantees.
- —Catch-up needs a replay log with per-client positions.
Follow-ups you should expect
Many interviews are decided in the follow-ups, not the first diagram.
Same shape, other products
The server has to speak first, to a lot of people, at the same time.
Capacity is measured in concurrent connections, not requests per second, and the hard part is the fan-out layer, not the socket.
Others with this shape: Live sports score · Live comments · Collaborative editor · Presence
How it is really built
Write your own answer first. Then read how teams who run this at scale describe it. Their constraints were real, and the write-ups often say what their choices cost.
- MDN — WebSockets API ↗The bidirectional alternative weighed against SSE in Stage 4.