Real-time game leaderboard inspired by mobile games and fantasy-sports contests: scores saved with a conditional update, Redis sorted sets for O(log n) ranks, rankings updated from a queue for global, daily, weekly and regional boards, score-range sharding, a cached top 100, friends ranks and asynchronous anti-cheat. A teaching design.
See why counting higher scores on every view collapses with millions of players.
What was missing: Nothing yet.
Why that's risky: Every rank lookup scans a large part of the table. With 25 million players, each view reads millions of rows, and views far outnumber matches.
What gets added: One game server that saves scores and finds a player's rank by counting every player with a higher score.
Trade-offs: Always exact, at the cost of a scan per view.
Use a data structure built for ranking, so a rank costs O(log n), not a scan.
What was missing: Ranks came from counting rows on every view.
Why that's risky: Each submission waits for two writes, and if the sorted-set update fails after the database write, the ranking silently drifts.
What gets added: Scores stay in the database as the source of truth, and a Redis sorted set holds every player ordered by score. ZREVRANK returns a rank and ZREVRANGE the top 100 in O(log n). Separate score and leaderboard services sit behind a load balancer.
Trade-offs: The sorted set is a second copy of every score, which costs memory, but a rank lookup becomes a microsecond operation.
Return as soon as the score is safe, and keep every leaderboard (daily, weekly, regional) in sync from one event.
What was missing: Submissions waited on the sorted set, and only one global leaderboard existed.
Why that's risky: One sorted set takes every write. A season-end rush or a tournament final makes it the bottleneck.
What gets added: The score service saves the score with a conditional update (only if higher), then publishes an event. Ranking workers apply it to every leaderboard it belongs to: global, daily, weekly and regional. Daily and weekly keys expire on their own.
Trade-offs: A new score shows up in rankings a moment after the match ends. Players rarely notice.
Spread the hot sorted set, and answer the questions players actually ask: the top, my rank, my friends.
What was missing: One sorted set took every read and write, and there was no friends leaderboard.
Why that's risky: A single load balancer, no limit on how often a client can submit, and no check for impossible scores.
What gets added: Sorted sets split by score range, so a player's global rank is their rank in their shard plus the sizes of the higher shards. A small cache holds each top 100, and friend ranks come from looking up each friend's score.
Trade-offs: Range shards need occasional rebalancing as scores grow. Hashing by player would avoid that but makes global rank a scatter-gather query.
Keep the leaderboard honest and up through a season-end rush.
What was missing: Nothing stopped impossible scores or a client hammering submit, and the load balancer and sorted sets had no spare.
Why that's risky: Remaining risk is low. A replica that falls behind can briefly show a slightly old rank.
What gets added: An anti-cheat worker that re-checks suspicious results and removes cheaters from every ranking, a per-player rate limiter, a second load balancer, a replica for each sorted-set shard, a sharded scores database, more service instances, and monitoring of ranking lag and shard load.
Trade-offs: Cheat checks run after the score is accepted, so a cheater can appear on the leaderboard for a few seconds before removal.
You're in the middle of an interview session. Leaving now will end your current attempt.
Explore concept overviews, real-system examples, key tradeoffs, and interview talking points for each roadmap section.
You've conquered this phase. These are the skills you now own: