The problem
A 1,000-player Swiss-format event generates ~500 simultaneous matches per round, all updating in real time, all visible to a public bracket page that may have 50,000+ viewers. The bracket engine has to stay consistent under that load and zero score gets lost or duplicated.
Architecture
Bracket state lives in a single source-of-truth Postgres table per tournament with a write-ahead log. Reads fan out via websockets to every connected client. Match score updates are conflict-resolved server-side using a CRDT-inspired merge: last-write-wins on simple fields, append-only for the audit log.
Score input race conditions
Two organisers updating the same match within 200ms used to drop one update on the floor. Fix: per-match optimistic concurrency token. The second writer gets a 409 with the current state and re-renders before retrying. Visible to the user as a 'match was updated, refreshing' toast.
Spectator scale
Public bracket pages serve a static-export HTML shell with websocket hydration. Up to 100K concurrent viewers per bracket page — viewers don't pay any DB cost; the websocket fan-out reads from a hot in-memory snapshot updated on every match commit.
What we don't do
We don't proxy stream video — embeds use the platform's own iframe (Twitch / YouTube / Kick). We don't store recorded match VODs ourselves. The bracket engine sticks to brackets.
The result
99.99% uptime across the 2025-2026 major-tournament season, including a 1,200-team Swiss-format winter open with 80K+ peak viewers. Median bracket-page-to-paint: 280ms.