Why should I use a Sorted Set for a live leaderboard in Redis?
Question
I'm designing a live leaderboard (the top 100 highest-scoring players) for a gaming platform; millions of players' scores change in real time. I want to keep the data in Redis. Instead of storing each player's score in a plain String key (`user:123:score`) and pulling all users to sort them every time, what are the architectural advantages and the time-complexity (O(log N)) analysis of using Redis's Sorted Set (ZSET) data type?
Answer
Short answer: storing scores as plain user:123:score strings and sorting in the app is O(N log N) per read over millions of keys — and you re-fetch everything each time. The right tool is a Sorted Set (ZSET).
The real point: the nature of a leaderboard is “sort and give me the top N.” If you try to do that work at read time, scale crushes you; you need to move the sorting to write time.
- O(log N) updates with
ZADD.ZADD leaderboard <score> <user>updates a member’s score in O(log N). When a player’s score changes it’s a single command; you don’t touch the whole table. The moment the score changes the set stays internally sorted. - Already-sorted top 100 with
ZREVRANGE.ZREVRANGE leaderboard 0 99 WITHSCORESreturns the top 100 players already sorted in O(log N + 100). You do no sorting on the app side; even with millions of players this read is near-constant cost. - One player’s rank with
ZREVRANK. “What rank am I?” is answered byZREVRANK leaderboard <user>in O(log N). With the string approach you’d have to fetch and count everyone; with a ZSET it’s a single command. - The skip-list sorts as you write. The skip-list behind a ZSET keeps everything ordered as you write. So the cost is spread to write time, not read time; reads stay cheap and almost independent of player count.
- Window large sets. For huge sets, use periodic snapshots and time-windowed boards (separate daily/weekly keys). Watch ties: equal scores order lexicographically; if needed, encode a tiebreaker (e.g. a timestamp) into the score to make the order deterministic.
Bottom line: a ZSET is purpose-built for live leaderboards; use it instead of strings + app-side sorting. The moment you move sorting out of read time and into write time, the leaderboard runs instant and cheap even with millions of players.
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.