Design a Real-Time Leaderboard

Intermediate · 20 min read · High-Level Design, Case Studies: Core

Sorted sets, O(log n) ranks, ties, monthly boards and sharding by score.

Design a real-time leaderboard for a mobile game. Players earn points by winning matches; the game shows the global top 10, each player's own rank, and the players just above and below them. Scores update in real time, and the leaderboard resets every month.

The core insight is that a relational database is a poor fit for "what is my rank?" at scale, while a sorted set answers it in O(log n). The interesting follow-ups are what happens when one machine is no longer enough, how to break ties fairly, and how to stop cheating.

1. Clarify the problem

2. Requirements

Functional: update a player's score after a match; return the top N; return any player's rank; return the players around a given player; keep past months' final standings.

3. Capacity estimation

So: the load is modest; the hard part is answering rank queries quickly, which a database table with ORDER BY score cannot do at this size.

4. Why not just a database?

Even with an index on (month, score), counting the rows above a player means scanning a large part of the index — millions of entries for an average player — on every rank request. Caching ranks does not help because every score change shifts the ranks of many players. This is the problem sorted sets solve.

5. Redis sorted sets

A sorted set keeps members ordered by score, backed by a skip list plus a hash map, so most operations cost O(log n):

6. High-level design

Update flow

7. Deep dives

Redis is fast but not the source of truth. Match results in the database are, so if Redis loses data the board can be rebuilt by replaying the month's score events (or summing the results table). Run Redis with a replica and persistence (AOF) to make that rare.

8. Failure modes

9. Trade-offs summary

10. What interviewers look for

Interview questions

  • Why can a sorted set return a rank in O(log n) when a database needs to count rows?
  • How do you find a player's global rank when the board is sharded by score range?
  • Two players reach 10,000 points. How do you rank the one who got there first higher?

Practice

Write your answer before opening the suggested one. Anything you mark "Partly" or "Missed it" comes back in your review deck.

Further reading

Key takeaways

  • Counting rows above a score does not scale; a sorted set (skip list with spans) gives O(log n) rank, top-N and range queries.
  • Keep match results in a database as the source of truth; Redis can be rebuilt from them.
  • Update scores asynchronously and idempotently; never trust client-reported scores.
  • Break ties by encoding the time a score was reached into the sort key.
  • Use a new key per period instead of resetting the board.
  • At very large scale, shard by score range so ranks stay cheap, or serve approximate ranks from a histogram.

Previous: Design Cloud File Storage (Dropbox) · Next: Design a Ride-Hailing Service