Skip to main content
Rift.
Back to Blog
Engineering10 min read

Inside the bracket engine: how Rift handles 1,000-player events

Priya Sharma

Head of Engineering · Mar 21, 2026

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.

PS

Priya Sharma

Head of Engineering at Rift

Contributing to the Rift blog with insights on product development, engineering, and best practices.

Try Rift free

See how Rift can transform your workflow.

Get Started
DemoUI kit preview — content is fictional.