The first move in any interview: define requirements and sketch the API before drawing a single box.
POST /v1/scores { user_id, points } → { rank }GET /v1/leaderboard?top=10 → [{ user_id, score, rank }]GET /v1/scores/{user_id} → { score, rank }GET /v1/leaderboard/around/{user_id}?range=4 → [...]Open any competitive game and you'll see a leaderboard: the top players, your own rank, and the handful of people just above and below you. It feels trivial until you do the math. With 25 million monthly players, computing 'what rank am I?' by sorting everyone on every request would melt a SQL database. The clean answer is a data structure most people never use directly: the Redis sorted set, which keeps millions of members ordered by score and answers rank queries in logarithmic time.
Here is the whole thing in plain terms. When a player wins a match, the game service validates the win (so nobody can fake a score from the client) and tells the leaderboard service to add a point. The leaderboard service calls ZINCRBY on a Redis sorted set, which bumps that player's score and instantly re-positions them in the ordering. To show the top 10, it calls ZREVRANGE for the highest scores. To show a single player's rank, it calls ZREVRANK, which returns their position directly without scanning. To show the four players above and below someone, it reads their rank and then grabs that small window around it.
The one idea worth getting straight is why a sorted set beats SELECT ... ORDER BY score LIMIT 10. A relational query has to sort (or at least scan an index over) a huge, constantly-changing table on every read. A sorted set keeps the members ordered as they change, so an insert, a score bump, or a rank lookup is all O(log n). Internally it's a skip list plus a hash map: the skip list keeps things ordered, the hash map jumps straight to any member.
Redis is fast but in-memory, so it isn't the source of truth. Each point is also written to MySQL, which stores the durable point history and player profiles (names, avatars). If the Redis node is lost, the leaderboard is rebuilt by replaying points from MySQL. And when one Redis node can't hold every player, you shard, either by fixed score ranges or by hashing across a Redis cluster and doing a scatter-gather to merge the top results. This system teaches sorted sets as the right tool for ranking, the cache-versus-source-of-truth split, and why rank queries are the part that doesn't scale on a plain database.