Sharding Decision Framework
Sharding splits one logical dataset across many databases. It buys scale and isolation at the price of permanent constraints, so the framework first asks whether it is needed at all and then focuses on the one decision that cannot easily be undone: the shard key.
How it works
A router maps each request's shard key to a shard. Hash placement spreads load evenly but loses range scans. Range placement supports ordered scans but can create hot partitions as new keys arrive. Directory placement stores key-to-shard mappings in a lookup table, enabling flexible rebalancing at the cost of a lookup dependency. Consistent hashing reduces data movement when shards are added.
Implementation steps
- Measure the actual bottleneck and rule out tuning, replicas, caching, and archival.
- List the top queries and transactions, and find the key present in most of them, such as tenant id.
- Check cardinality and skew of the candidate key against production data.
- Choose a placement scheme and a number of logical shards well above the physical node count, so shards can move between nodes.
- Keep global data, such as reference tables, replicated or in an unsharded store.
- Replace cross-shard transactions with sagas, or redesign aggregates to fit within one shard.
- Rehearse shard splits and moves before they are urgent.
Common pitfalls
- Choosing a monotonically increasing key with range placement, which concentrates writes on the newest shard.
- Sharding by a key that few queries filter on, causing scatter-gather.
- One very large tenant overwhelming its shard.
- Globally unique id generation forgotten until inserts collide.
- No tooling for moving a logical shard.
Metrics to watch
- Per-shard CPU, storage, and write rate skew.
- Share of queries that hit more than one shard.
- Hot key request concentration.
- Shard rebalance duration.
- Router lookup latency and error rate.
Example configuration
sharding:
key: tenant_id
placement: hash
logicalShards: 256
physicalNodes: 8
globalTables: [currencies, countries]
crossShardTransactions: forbidden
largeTenantPolicy: dedicated-shard-above-5pct-load
Practical rollout
Write the decision down as a short record containing the measured bottleneck, the options rejected, the chosen key with skew analysis, and the expected capacity runway. Revisit it when assumptions change, for example when a single customer grows large. Prototype the routing layer and a shard move on non-production data first, because the first real rebalance is the worst time to discover missing tooling or unsafe assumptions. Share the record with every team that touches the data.
Key takeaways
- Shard only after simpler scaling options are exhausted.
- The shard key must match dominant access patterns and spread load.
- Use many logical shards on few nodes to keep rebalancing cheap.
- Design away cross-shard transactions.