Skip to content
C Codeloom
System Design

System Design: Real-Time Leaderboard with Redis

Design a real-time leaderboard using Redis sorted sets, handling millions of score updates per second with low latency rankings.

·3 min read · By Codeloom
Intermediate 10 min read

What you'll learn

  • How sorted sets power leaderboards
  • Sharding by region or game
  • Handling ties and percentile queries
  • Persisting scores reliably
  • Designing for spiky traffic

Prerequisites

  • Familiar with HTTP and databases

What and Why

Leaderboards reward competition and drive engagement. The challenge is showing accurate rankings in real time as scores change, often with millions of players and short bursts of activity around tournaments or events.

A naive relational query ORDER BY score DESC LIMIT 100 does not scale once your player table has tens of millions of rows. We need a structure that maintains ordering as a side effect of writes.

Mental Model

Redis sorted sets (ZSET) are the perfect primitive. They keep members sorted by score and offer O(log N) inserts, updates, and rank lookups. A leaderboard is essentially one sorted set per scope (global, weekly, per-region).

Architecture

Game servers send score updates to a leaderboard service. The service writes to Redis with ZADD and asynchronously persists to a durable database for analytics and audit.

Player -> Game Server -> Leaderboard Service
                            |
                            +--> Redis ZSET (live ranks)
                            |
                            +--> Queue -> DB (durable record)

Client -> API -> Redis ZRANGE -> top N
            -> Redis ZREVRANK -> player's rank
Leaderboard write and read paths

ZRANGEBYSCORE and ZREVRANGE return top N or page through results. ZSCORE returns a player’s current score; ZREVRANK returns their rank. For “show me the 5 players above and below me,” combine ZREVRANK with a windowed ZRANGE.

For global leaderboards with hundreds of millions of players, shard by score band. Keep a smaller, full-detail set for the top 10k and approximate ranks for everyone else with histograms.

Trade-offs

Sorted sets are memory-hungry. Each entry costs 60-100 bytes. A billion players will not fit on one node. Sharding adds complexity to ranking queries that cross shards.

Eventual consistency is usually fine for ranks beyond the top 100, but the top of the board demands stronger guarantees because users see it directly. Pin the hottest scope to a single shard for ordering.

Real-time updates conflict with anti-cheat. You may need to delay or quarantine suspicious scores before they hit the public board.

Practical Tips

Use weekly or daily leaderboards by including the period in the key: lb:weekly:2026-W26. TTL old keys to keep memory bounded. Snapshot the final state to your durable store before TTL expires.

Avoid hot-key contention by batching updates server-side. If a single player updates 100 times per second, debounce to the highest score in a small window.

For ties, sorted sets use lexical order on the member. To break ties by earliest submission, encode a timestamp into the score: score * 1e9 - timestamp.

Use ZADD GT to only update if the new score is greater than the current one. This prevents accidental regressions from out-of-order events.

Wrap-up

Redis sorted sets turn what looks like a hard ranking problem into a few atomic commands. The interesting design work is around persistence, sharding, and protecting the system from abuse. Start with one ZSET per scope, then peel off the hot regions as you grow.