Skip to main content
BLUEPRINT #03Social & Real-Time

Design a Real-Time Gaming Leaderboard

Target AWS Architecture:DynamoDBS3ElastiCacheKinesis
10-Stage Structure:1. Requirements→2. Sizing→3. Topology→4. Data Model→5. AWS Topology→6. Deep-Dive→7. Failures→8. SRE Playbooks

1. Problem Statement & Scope Clarification

System Mission

Design an ultra-low-latency, real-time gaming leaderboard service (similar to Xbox Live, PlayStation Network, and competitive esports platforms) capable of processing hundreds of thousands of score updates per second, maintaining exact global rankings across tens of millions of players, and delivering Top-NN and surrounding rank windows in under 5 milliseconds.

Functional Requirements

  1. Score Submission (SubmitScore): Ingest and atomically update a player's score for a specific game and season, recalculating their global rank in real time.
  2. Top-NN Global Leaderboard (GetTopRankings): Retrieve the current top NN players (e.g., Top 100) with ranks, usernames, avatars, and verified scores.
  3. Surrounding Player Window (GetSurroundingRanks): Retrieve a specific player's exact rank along with MM players directly above and below them (relative ranking window).
  4. Deterministic Tie-Breaking: Automatically break score ties by awarding the higher rank to the player who achieved the score earlier in time.
  5. Periodic & Seasonal Reset: Support daily, weekly, and seasonal leaderboard archival and zero-downtime rollover.

Non-Functional Requirements (SLAs & SLOs)

  • Availability: 99.999%99.999\% uptime .
  • Latency:
    • Read Latency (Top-NN and Relative Window): P99<5Β msP99 < 5\text{ ms}.
    • Write Latency (Score Ingest & Rank Calculation): P99<15Β msP99 < 15\text{ ms}.
  • Throughput: Support >100,000Β scoreΒ submissions/sec> 100,000\text{ score submissions/sec} during global live gaming events.
  • Accuracy: 100%100\% linearizable rank precision for top-tier competitive play (no stale or skipped ranks).

2. Capacity & Scale Estimation (Back-of-the-Envelope Math)

Player Base & Ingest QPS

  • Total Registered Players: 50,000,00050,000,000 (50MΒ players50\text{M players}).
  • Daily Active Players (DAU): 10,000,00010,000,000 (10MΒ DAU10\text{M DAU}).
  • Average Ingest : AverageΒ IngestΒ QPS=10Γ—106Γ—50Β matches/day86,400Β secβ‰ˆ5,787Β updates/sec\text{Average Ingest QPS} = \frac{10\times 10^6 \times 50\text{ matches/day}}{86,400\text{ sec}} \approx \mathbf{5,787\text{ updates/sec}}
  • Peak Ingest (18Γ—18\times spike factor during esports tournaments): PeakΒ IngestΒ QPS=100,000Β updates/sec\text{Peak Ingest QPS} = \mathbf{100,000\text{ updates/sec}}
  • Read (Top-NN views from game menus): PeakΒ ReadΒ QPS=50,000Β reads/sec\text{Peak Read QPS} = \mathbf{50,000\text{ reads/sec}}

Memory Footprint Derivation (Redis Sorted Set)

A ZSET uses a dual-structure: a SkipList (for O(log⁑N)O(\log N) range scans) and a Hash Table (for O(1)O(1) score lookups):

  • Member ID (usr_998124): β‰ˆ16Β bytes\approx 16\text{ bytes}
  • Score (float64 IEEE-754 double precision): β‰ˆ8Β bytes\approx 8\text{ bytes}
  • SkipList Node pointers (forward/backward pointers, level spans): β‰ˆ32Β bytes\approx 32\text{ bytes}
  • Hash Table dictionary entry: β‰ˆ24Β bytes\approx 24\text{ bytes}
  • Jemalloc memory alignment overhead: β‰ˆ16Β bytes\approx 16\text{ bytes}
  • Total per Player Record: β‰ˆ96Β bytes\approx 96\text{ bytes}.

ActiveΒ LeaderboardΒ Memory=50,000,000Β playersΓ—96Β bytesβ‰ˆ4.8Β GBΒ RAM\text{Active Leaderboard Memory} = 50,000,000\text{ players} \times 96\text{ bytes} \approx \mathbf{4.8\text{ GB RAM}} With 3x replication and multiple game modes (10 game modes Γ—4.8Β GB=48Β GB\times 4.8\text{ GB} = 48\text{ GB}), a cluster of 3 cache.r6g.xlarge nodes (26.32 GiB RAM each) easily holds the entire state in memory.


3. High-Level Architecture & AWS Component Mapping

Interactive Architecture Diagram
Synthesizing vector architecture diagram...

4. API Interface Design & Tie-Breaking Score Math

1. Deterministic Microsecond Tie-Breaking Formula

If Player A and Player B both achieve a score of 50,00050,000, standard ZSET orders members lexicographically by their user_id. To guarantee that the player who scored first gets the higher rank, we encode epoch milliseconds into the fractional decimal bits:

CombinedΒ Score=Sraw+(1.0βˆ’Tnow_ms1013)\text{Combined Score} = S_{\text{raw}} + \left( 1.0 - \frac{T_{\text{now\_ms}}}{10^{13}} \right)

Where Tnow_msT_{\text{now\_ms}} is the millisecond timestamp when the score was achieved. Since Tnow_msT_{\text{now\_ms}} grows monotonically, an earlier timestamp yields a slightly larger fractional value, guaranteeing deterministic first-achiever precedence:

text
Score A (at t=1000): 50000 + (1 - 0.000000001000) = 50000.999999999000
Score B (at t=2000): 50000 + (1 - 0.000000002000) = 50000.999999998000
-> Score A > Score B (Player A is ranked higher)

2. gRPC Interface Specification (leaderboard.proto)

protobuf
syntax = "proto3";

package hispeeddesign.leaderboard.v1;

service LeaderboardService {
  rpc SubmitScore (SubmitScoreRequest) returns (SubmitScoreResponse);
  rpc GetTopRankings (GetTopRankingsRequest) returns (GetTopRankingsResponse);
  rpc GetSurroundingRanks (GetSurroundingRanksRequest) returns (GetSurroundingRanksResponse);
}

message SubmitScoreRequest {
  string game_id = 1;
  string season_id = 2;
  string user_id = 3;
  double raw_score = 4;
  string match_verification_token = 5;
}

message SubmitScoreResponse {
  int64 global_rank = 1;
  double verified_score = 2;
  bool is_new_high_score = 3;
}

message GetTopRankingsRequest {
  string game_id = 1;
  string season_id = 2;
  int32 top_n = 3;             // Default: 100
}

message LeaderboardEntry {
  int64 rank = 1;
  string user_id = 2;
  string username = 3;
  string avatar_url = 4;
  double score = 5;
}

message GetTopRankingsResponse {
  repeated LeaderboardEntry entries = 1;
  int64 total_participants = 2;
  int64 last_updated_epoch_ms = 3;
}

message GetSurroundingRanksRequest {
  string game_id = 1;
  string season_id = 2;
  string user_id = 3;
  int32 radius = 4;            // e.g. 5 (fetches 5 above and 5 below)
}

message GetSurroundingRanksResponse {
  int64 user_rank = 1;
  repeated LeaderboardEntry surrounding_entries = 2;
}

Part 2: Production Deep-Dive Locked1 Coin = 24 Hours

Unlock Complete Architecture & Production Runbooks

Your Balance:40 Coins

You have explored the free architectural preview (~44%). Spend 1 Coin to unlock the remaining 7 production deep-dive sections for a full 24 hours.

Sections Included in This 24-Hour Pass:
5. Data Models & DynamoDB Profile Cache Schema
6. Detailed Request Flow & Redis Workflows
7. Leaderboard Architecture Trade-Off Matrix
8. Failure Modes, Resiliency & Critical Edge Cases
9. Production Pitfalls & Anti-Patterns (The "Gotchas")
10. Production Runbook & Observability Guide
11. Interview Strategy & System Design Rubric
Keeps page unlocked for exactly 24 hoursSpend coins to fund LLM & compute infrastructure