Gaming & realtime, an interactive architecture walkthrough
Real-time leaderboard: how the architecture works
How a real-time leaderboard ranks millions of players with in-memory sorted sets, takes scores only from game servers, and rolls boards over by season.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate.
Interactive diagram
Overview
A real-time leaderboard ranks players by score and answers three questions quickly: who is at the top, what is my exact rank, and who is just above and below me. A sorted set in memory answers each in logarithmic time, so rank is computed live instead of by a nightly batch job. Scores are submitted by authoritative game servers, de-duplicated and checked, and applied through a partitioned event stream.
The sorted set is fast but not the only copy: each player's best score is also kept in a relational database, and boards are rebuilt from it if the in-memory copy is lost. Seasonal and daily boards are separate keys created on a schedule, and closed seasons are archived to object storage. This is a simplified learning design, not any game's production system.
Trade-offs and what changes at scale
One sorted set lives on one Redis shard, which caps the size and write rate of a single board; very large games split boards by region or season, or compute approximate ranks for players far from the top by bucketing scores. Redis replication is asynchronous, so a failover can lose recent updates, which is why the database is the source of truth. Ties need a rule, and packing the tie-break into the score has to stay within the 53 bits a double holds exactly. Caching the top N for a second or two trades a little freshness for a large drop in read load.
How it works, step by step
The walkthrough above, as text. Each step lights up the components named under it.
When a match ends, the Game Server, not the player's device, submits the result through the API Gateway. Scores reported by clients are easy to forge, so only the authoritative server can write.
The Score Ingest Service verifies the server's signature, drops duplicates by match id and runs the Anti-cheat Checker for impossible values. Retries from the game server then cannot count a match twice.
Accepted scores go to the Score Events topic, partitioned by leaderboard id so each board's updates are applied in order. A burst at the end of a tournament queues here instead of overloading Redis.
The Leaderboard Workers first upsert each player's best score in the Score DB, updating only if the new score is higher. This durable copy is what a board is rebuilt from if Redis loses data.
The workers then write the score into the board's entry in the Leaderboard Sorted Sets with ZADD GT, which only raises a score and runs in O(log N). Ties are broken by packing the score and an earlier-is-better timestamp into one number that stays within the range a double stores exactly.
The most requested view, the top 100, is read from the sorted set once and kept in the Top-N Cache for a second or two. Thousands of players opening the board then cost one Redis range query, not thousands.
For "my rank", the Leaderboard API calls ZREVRANK on the sorted set and then ZRANGE for the players just above and below. Both are logarithmic, so a player's exact rank among millions is computed live.
A friends board gets the player's friend ids from the Friends Service, reads their scores from the sorted set and sorts that small list in the API. Names and avatars come from the Profile Service, so the sorted set stores only player ids.
The Rank Notifier watches the same score events and pushes a message through the Realtime Gateway when a player enters the top 100 or passes a friend. Pushing only meaningful changes avoids streaming every rank shift to every player.
The Season Scheduler starts each season or daily board under a new key instead of clearing the old one. Writes switch to the new key at a set time, so there is no moment when the board is empty.
When a season closes, the Snapshot Worker copies the final standings to the Season Archive and the old key is given an expiry. Prize payouts are then computed from a frozen copy that later writes cannot change.
Score events also load into the Analytics Store for score distributions and cheat review, while Observability tracks ingest lag and Redis memory per board. One very large board lives on a single Redis shard, so its size is watched closely.
Sequence diagram
The same walkthrough as a UML sequence diagram, one lane per layer or group (20 components in all), left to right in the order a request reaches them, numbered by step. A loop on a lane is a step that stays inside that group. Solid arrows are synchronous calls, dashed are asynchronous.
Key components
Edgelayer
- API Gateway: auth, rate limits, routing
- Realtime Gateway: pushes rank changes (websocket)
Players & Gameslayer
- Game Client: shows ranks, never reports scores
- Game Server: authoritative match results
Score Ingestdomain
- Anti-cheat Checker: flags impossible scores
- Score Events: partitioned by leaderboard id (kafka)
- Score Ingest Service: verify signature, de-dup by match id
Rankingdomain
- Leaderboard Sorted Sets: one sorted set per board (redis)
- Leaderboard Workers: apply scores to boards
- Score DB: best score per player per board (postgresql)
Querydomain
- Friends Service: friend lists for friend boards
- Leaderboard API: top N, my rank, players around me
- Profile Service: names, avatars, country
- Rank Notifier: detects rank changes worth pushing
- Top-N Cache: top 100 per board, 1-2 s TTL (redis)
Seasons & Recoverydomain
- Season Archive: frozen final standings (s3)
- Season Scheduler: opens and closes boards
- Snapshot Worker: final standings, rebuilds boards
Analytics Store
- Analytics Store: score distributions, cheat review (clickhouse)
Observability
- Observability: ingest lag, Redis latency, memory
Sources
Public writing this explainer draws on. Read these for what the real systems actually do.
Make it yours
Copy this diagram and its walkthrough into your own workspace, then change anything: swap Postgres for DynamoDB, add a cache, rewrite the narration. Free, and it uses no AI credits.
Related walkthroughs
- Multiplayer game backendHow a multiplayer game backend matches players by skill and latency, runs each match on an authoritative server, and processes results afterwards.
- Maps and navigationHow a maps system serves vector tiles from a CDN, routes over a preprocessed road graph with live traffic weights, and builds traffic from GPS traces.
- Social news feed (Twitter-style timeline)How a social feed pushes posts into follower timelines, handles accounts with millions of followers by merging at read time, and ranks the result.
This is a learning explainer based on public engineering writing and general design practice. It is simplified, it is not the actual architecture of any company, and it may be inaccurate. Real systems differ in the details. Browse the library.