1Show the Level 1 solution
2**A.**
31. **Bad.** Few values and very uneven (a few countries hold most users).
42. **Good.** Many values, even spread, and most order queries include the user.
53. **Bad** under range sharding: every new event goes to the newest shard. Use a hashed key or `(source, time bucket)`.
64. **Mixed.** Fine for the 5,000 small tenants, but the 3 huge ones become hot. Use directory routing to give each big tenant its own shard.
75. **Bad.** A handful of values, and most orders share one status.
8
9**B.**
101. **One shard** (the user's).
112. **Every shard** (or a precomputed counter or analytics store).
123. **Every shard**, unless the order ID contains the shard or you keep an `order_id → shard` index. That's why IDs with the shard inside are handy.
134. **One shard.**
Show the Level 2 solution
1. 2,000,000,000 × 1 KB = 2 TB ÷ 250 GB = **8 shards**; × 3 copies = **24 servers**.
2. 20,000 ÷ 8 = **2,500 a second** per shard. At 40% on one shard: **8,000 a second**, more than three times its fair share.
3. Mod N: about **80%** (4 out of 5). Logical shards: about **20%** (1 out of 5), moved as whole buckets.
4. 1 − 0.99¹⁶ ≈ **15%** of dashboard loads.
1Show the Level 3 solution
2Tested solution (Python 3), the key part:
3
4```python
5class LogicalShardRouter:
6 def __init__(self, n_logical, servers):
7 self.n_logical = n_logical
8 self.owner = {ls: servers[ls % len(servers)] for ls in range(n_logical)}
9
10 def logical(self, key):
11 return h(key) % self.n_logical # fixed forever: keys never re-hash
12
13 def shard_for(self, key):
14 return self.owner[self.logical(key)]
15
16 def add_server(self, new_server):
17 servers = sorted(set(self.owner.values())) + [new_server]
18 target = self.n_logical // len(servers)
19 per_server = Counter(self.owner.values())
20 moved = 0
21 for ls in range(self.n_logical): # hand whole buckets to the new server
22 old = self.owner[ls]
23 if per_server[old] > target and per_server[new_server] < target:
24 self.owner[ls] = new_server
25 per_server[old] -= 1
26 per_server[new_server] += 1
27 moved += 1
28 return moved
29```
30
31All checks pass: growing from 4 to 5 servers moves **80%** of keys with mod N, and **20%** (204 of 1,024 buckets) with logical shards. The full file, including the range, hash and directory routers and scatter-gather, is in `code/ch15_sharding.py`.
1Show the Level 4 solution
2**The bug:** the shard key is **order date**, sharded by **range**. Every new order has today's date, so **all new orders go to the last shard**. During the sale, that shard takes 100% of the writes while the others hold old orders and sit idle. In the tested demo, all 10,000 of today's orders land on one shard.
3
4**The fix:** shard by a high-cardinality key that spreads writes, **hashed `user_id`**:
5
6```python
7def shard_for_order(order):
8 return logical_router.shard_for(order.user_id)
9```
10
11Now today's orders spread across all shards (about 2,500 each in the demo).
12
13**Monthly reports:** they now span every shard. Don't run them as scatter-gather on live shards; stream order changes into an **analytics store** (or a reporting replica of each shard) and run reports there (Chapter 22).
1Show the Level 5 (sketch) solution
21. **Shard key:** `user_id`, hashed into **1,024 logical shards** mapped to 8 physical shard groups at first. Orders, order items, payments and the cart share the key, so checkout is a single-shard transaction.
32. **Orders by book:** a global secondary index table `(book_id, order_id, user_id)` sharded by `book_id`, updated from the order change stream. **Reports:** change streams into an analytics warehouse; nightly reports run there.
43. **IDs:** Snowflake-style 64-bit order IDs with the logical shard number inside, so an order ID can be routed directly (Chapter 10). **Unique email:** an `emails` table sharded by email; sign-up claims the email first.
54. **Adding shards:** add a server, move whole logical shards to it (copy, catch up, switch the map, verify, delete) with Vitess or Citus-style tooling, one bucket at a time, off-peak.
65. **Replication:** each shard group has a leader and two replicas in three Mumbai zones (one semi-synchronous); European users read browsing data from asynchronous replicas in Frankfurt.
76. **Cross-shard transaction:** a gift order where Asha (shard 3) pays for an order delivered to Ravi (shard 6), and both accounts must be updated. Handle it with a **saga**: create the order and charge Asha on her shard, then record the gift on Ravi's shard; if the second step fails, run a compensating refund (Chapter 17).