SystemDesign.io
Track 2: data-layerID: sharding-strategy-design
Mode: structuredDifficulty: intermediate-advanced⏱️ 20 mins
Module · Data Layer · 20 min

Database Sharding — Divide & Conquer at Scale

You scaled your reads with Replication, but your Primary DB is drowning in write traffic. When a single machine can no longer hold your entire dataset, it's time to split the database itself across multiple servers.

01 / Concept Cards (Theory)

Sharding Strategies & Architecture

Understand why Replication hits a ceiling, how Sharding breaks through it, and the 3 core partitioning strategies used in production.

1. Why Replication Is Not Enough: The 3 Hard Walls

In the previous module, you mastered Leader-Follower Replication — it scales read throughput beautifully. But Replication hits 3 physical limits that cannot be solved by adding more replicas:

🔥 Wall #1: Write Bottleneck

Why it occurs: In replication, all database saves (INSERT/UPDATE) must go to a single Primary server so data stays consistent. As user activity surges, that one machine hits a hard limit on how many simultaneous write requests it can process and save.

🚗 Real-World Example (Uber):During peak hours, 5 million drivers send GPS updates every 4 seconds. That's over 1.25 million writes per second. A single Primary database crashes trying to save all of them. Adding 20 Read Replicas does not help because replicas only accept reads.
💾 Wall #2: Storage Limit

Why it occurs: In replication, every replica holds an exact duplicate copy of the entire database. When total data grows past what a single physical machine can store, you run out of drive capacity, and search queries slow down drastically because the database cannot fit its search indexes into fast memory.

📸 Real-World Example (Instagram):Instagram stores billions of user photos, comments, and likes totaling over 500 Terabytes of database records. No single computer exists that can store and quickly search a single 500 TB table.
🔄 Wall #3: Replication Lag & Network Overload

Why it occurs: Whenever the Primary writes a new record, it must immediately send that update over the network to every replica. With massive write traffic and many replicas, the Primary spends immense bandwidth and processing power just broadcasting copies, causing replicas to fall behind.

🐦 Real-World Example (Twitter / X):During a live sports final, 100,000 tweets are posted per second. Broadcasters copy these writes to 15 Read Replicas. The replicas lag 30 seconds behind, so when users post a reply and refresh, their own reply hasn't appeared yet.
💡 The Mental Model Shift: "Duplicate" vs "Divide"
Replication = DUPLICATECopy the same full dataset across N servers. Scales read throughput and high availability. Cannot scale writes or storage.
Sharding = DIVIDESplit the dataset into smaller chunks across N servers. Each shard handles its own reads AND writes. Scales writes, storage, and throughput.

2. The 3 Core Sharding Strategies

Horizontal Partitioning (Sharding) splits rows of a table across multiple database servers. The critical decision is: how do you decide which rows go to which shard?

🔢 Range-Based ShardingSplit rows by value rangesAssign rows based on a continuous range of the shard key.

Example: Users A–M → Shard 1, Users N–Z → Shard 2.

✅ Pros: Simple to implement. Great for range queries (WHERE created_at BETWEEN ...).
❌ Cons: Traffic hotspots — if most usernames start with "S", Shard 2 gets hammered while Shard 1 idles.
#️⃣ Hash-Based ShardingHash the key, mod by shard countshard = hash(user_id) % N

Example: hash(42) % 3 = 1 → Shard 1.

✅ Pros: Extremely uniform data distribution. No hotspots.
❌ Cons: Adding/removing shards changes N, reshuffling almost all data. Range queries become impossible across shards.
📖 Directory-Based ShardingCentral lookup table maps keys → shardsA separate service maintains a mapping: user_id → shard_location.

Example: Lookup says user 42 → Shard 3.

✅ Pros: Maximum flexibility. Can move individual users between shards without disruption.
❌ Cons: Lookup service becomes a single point of failure and a latency bottleneck.

3. Visualizing the Shard Router & Hash-Based Routing

Watch the live query routing below: The Shard Router receives queries, computes hash(key) % 3, and sends each query to the correct shard.

⚡ Hash-Based Shard Routing — Live Query Distribution
🖥️ App ServerIncoming Queries🔀 Shard Routerhash(key) % 3Query Coordinatorhash%3 = 0hash%3 = 1hash%3 = 2💾 Shard 1 (Node A)Stores Users 0%–33%💾 Shard 2 (Node B)Stores Users 34%–66%💾 Shard 3 (Node C)Stores Users 67%–100%Incoming QueryShard 1 Route (Rem = 0)Shard 2 Route (Rem = 1)Shard 3 Route (Rem = 2)

4. The Shard Key Dilemma & The Celebrity Hotspot Problem

Choosing your shard key is the most critical decision in database partitioning. A poor choice causes hotspots, where one server catches fire while the rest sit idle.

1. The ProblemThe 100% CPU Meltdown

Imagine you shard an Instagram-like platform by author_id across 4 database shards. It works great until a mega-celebrity (like Cristiano Ronaldo or Lionel Messi with 100M followers) posts a viral photo.

🚨 The Crisis: Within 60 seconds, 30 million users rush to like and comment. Because every single request has author_id = 'ronaldo', 100% of those 30M requests slam into Shard 3. Shard 3 crashes, taking down normal users on that shard, while Shards 1, 2, and 4 sit at 1% CPU doing nothing.
2. The Root CauseWhy the Math Broke Down

The routing algorithm is deterministic: hash(author_id) % 4.

  • Sharding is designed to distribute different keys evenly across machines.
  • However, sharding cannot split millions of queries for the EXACT SAME key.
  • Since every like and comment points to the same author, every single query resolves to the exact same shard number. Adding 100 more shards does not help because all 30M queries will still hit Shard 3.
3. The SolutionHow Senior Architects Solve the Celebrity Problem

To survive mega-celebrities, production architectures use two core techniques:

🧂 Deep Dive: Key Salting (For Massive Write Traffic)

The Idea: If writing to one single key chokes a database shard, we mathematically split that one key into 10 random sub-keys. Here is how writes and reads work step-by-step:

✍️ STEP 1: How Writes Work (Random Scattering)When a user likes Ronaldo's post (post_101), the App Server randomly generates a number between 0 and 9 (the "salt"):
User A likes post → App creates key: post_101_3hash('post_101_3') % 4 = Shard 0
User B likes post → App creates key: post_101_7hash('post_101_7') % 4 = Shard 2
User C likes post → App creates key: post_101_1hash('post_101_1') % 4 = Shard 1
✅ Result: 30 million writes are spread evenly across all 4 database shards instead of crushing Shard 3.
📖 STEP 2: How Reads Work (Scatter-Gather Aggregation)When someone opens the post to see the total like count, the application queries all 10 salted sub-keys in parallel:
SELECT SUM(count) FROM likes WHERE post_id IN ('post_101_0', 'post_101_1', ..., 'post_101_9');
The app sums the 10 numbers together in memory (1.2M + 1.1M + ... = 12M likes). Because querying 10 shards in parallel takes <5ms, the tiny read cost is 100% worth the massive 10× write scale.
⚡ STEP 3: Adaptive Salting (Only Salt Hot Entities)You don't salt regular users who only get 20 likes (that would waste read queries). The system maintains a metadata flag: only accounts with >100k followers or posts with high write velocity trigger salting.
⚡ Solution #2: In-Memory Caching (For Massive Read Traffic)

For viral posts being viewed by millions simultaneously, place a Redis / CDN edge cache in front of the database. 99.9% of read requests are served directly from RAM in 1ms, completely shielding the database shards from read storms.

SummaryThe 3 Golden Rules for Picking Any Shard Key
① High CardinalityMust have millions of distinct values (e.g. user_id). Avoid low-cardinality fields like country (~200 values max).
② Uniform DistributionData & traffic must be evenly spread. No single key should represent 10%+ of total traffic.
③ Query AlignmentThe key should appear in the WHERE clause of 90% of queries to avoid expensive cross-shard lookups.

5. Sharding Challenges & Operational Pitfalls

Sharding is powerful but introduces significant complexity. Here are the key trade-offs every engineer must understand:

🔗 Cross-Shard Joins & Queries

If a query needs data from two different shards (e.g. "find all orders by User 42 AND Product reviews for item 99"), the coordinator must query multiple shards and merge results in memory — extremely expensive.

📦 Re-sharding (Adding More Shards)

When a shard fills up, you must redistribute data across new shards. With hash-based sharding, changing N in hash(key) % N moves almost every row. Consistent Hashing solves this (covered in Track 4).

🔑 Unique ID Generation

Auto-increment IDs don't work across shards (Shard 1 and Shard 2 would both create id=1). Solutions: UUID, Twitter Snowflake IDs, or a centralized ID generator service.

🤝 Distributed Transactions

BEGIN TRANSACTION across shards requires a 2-Phase Commit (2PC) protocol — slow, complex, and a partial failure can leave data in an inconsistent state. Most apps avoid cross-shard transactions entirely.

6. The Full Picture: Sharding + Replication Combined

In real production systems, sharding does NOT replace replication — they combine. Each shard is its own replicated cluster:

🏗️ Production Architecture — Each Shard Is a Replicated Cluster
🔀 Shard Routerhash(key) % 2SHARD 1 CLUSTER (Users A–M)👑 Primary📖 R1📖 R2SHARD 2 CLUSTER (Users N–Z)👑 Primary📖 R1📖 R2⚡ Sharding Provides:Write scaling & total storage scalingEach shard operates independent writes🔄 Replication Provides:Read scaling & high availabilityFollower failover inside each shard🏗️ Combined Result:Infinite horizontal scalabilityfor Reads, Writes, AND Storage

7. Interactive Sharding Scenario Quiz

Test your sharding knowledge with real-world scenarios:

📱 A social media app has 200 million users. The database is 8 TB and growing. Read replicas handle reads fine, but the Primary DB is at 98% CPU from write traffic (50K writes/sec). What should you do?
✅ Shard by user_id is correct! The bottleneck is write throughput on a single Primary. Adding read replicas doesn't help writes. Sharding distributes both writes and storage across multiple independent Primary servers.
🏪 An e-commerce platform shards its orders table by country_code. 40% of orders come from the US and 25% from India. Users report that the site is slow during US business hours. What went wrong?
✅ Hotspot from bad shard key! country_code has very low cardinality (~200 countries) and extremely uneven distribution (65% of traffic hits 2 shards). A better shard key would be order_id or user_id which distribute uniformly.
💬 A chat app shards messages by hash(user_id) % 4. A product manager asks: "Can we add a feature to search all messages containing the word 'meeting' across all users?" What's the architectural concern?
✅ Cross-shard scatter-gather! A keyword search across all users requires querying ALL 4 shards, merging results in memory, and sorting — an expensive O(N) fan-out. The solution is usually a separate search index (like Elasticsearch) that indexes across all shards.
🎵 A music streaming service uses hash(song_id) % 3 to shard its catalog. A new viral hit gets 10 million plays in one hour. Is there a problem?
✅ Celebrity Problem! Hash-based sharding distributes different keys evenly, but all 10 million reads for the same song_id still hit the exact same shard. Mitigation: cache the hot song in Redis/CDN, or append random suffixes to scatter reads.

8. System Design Interview Comparison Matrix

Sharding strategies quick reference table:

DimensionRange-BasedHash-BasedDirectory-Based
Data DistributionUneven (depends on key range)Uniform (hash function guarantees)Flexible (manually controlled)
Range QueriesEfficient (single shard scan)Expensive (fan-out to all shards)Depends on mapping design
Adding New ShardsEasy (extend the range)Hard (rehash redistributes most data)Easy (update lookup table)
Hotspot RiskHigh (popular ranges overloaded)Low (unless Celebrity Problem)Low (can manually rebalance)
ComplexityLowMediumHigh (extra lookup service)
Used ByMongoDB (range), HBaseCassandra, DynamoDB, Redis ClusterVitess (YouTube), Custom solutions
02 / Practice Exercise

Build Your Sharded Architecture

Design a horizontally partitioned database architecture: Route client traffic through an App Server to a Shard Router, then distribute queries to the correct database shards.

Interactive CanvasMode: Freeform Drag & Connect

Task: Hash-Based Sharded Database Cluster

🎯
Scenario Prompt: Wire up a sharded architecture: Connect the Client to the App Server, the App Server to the Shard Router, and the Shard Router to each of the 3 database shards (Shard 1, Shard 2, Shard 3).
Available Components (Click to place on canvas):
🖱️Canvas is emptyClick components above to place them onto the canvas.
Drag components to arrange them freely, and click two nodes to connect them.
💡 Drag to move • Click Node A ➔ Node B to connect • Click ✕ to delete