Usernames

A page of the leaderboard shows 50 usernames. The sorted set holds only player IDs and scores. The usernames are in the players table of the player database. Let’s consider where the leaderboard service gets them.

Asking the player service

The leaderboard service could ask the player service for the 50 usernames on each page. That adds one request to the player service for every page. And when the player service is down, the leaderboard cannot show its pages either.

Reading the player database

The leaderboard service could read the usernames from the player database. But the 50 players on a page are spread over the shards by player ID, so every page needs lookups on many shards. Those lookups add load to the database the game service writes to. And the leaderboard service again depends on the layout of a table it does not own.

Keeping a copy

I keep a copy of the usernames in Redis, next to the sorted sets: a map from player ID to username. The message that a game ended already carries both usernames, so the leaderboard service updates the map whenever it updates a score.

This is denormalization. The username is stored in the player database, and a copy is stored in the leaderboard’s data, so that the leaderboard service does not have to look it up elsewhere for each page.

For a page, the leaderboard service gets the 50 player IDs from the sorted set, then their usernames from the map.

The cost of the copy

If a player changes their username, the leaderboard shows the old one until the player’s next game. Usernames rarely change, so I accept this.