Sharding strategies
Range, hash, and consistent-hash — the trade-offs and hot-key traps.
When one machine can't hold all your data, you split it — sharding. But the choice of how to split is the single biggest ops decision you'll make for the life of the database. Get it right and you scale smoothly for a decade. Get it wrong and you rewrite everything two years later when the shard key becomes a hot spot.
There are four industrial strategies: Hash sharding (spread evenly by key hash), Range sharding (keys split by value range), Geographic sharding (partition by user location), and Directory-based sharding (a lookup table maps keys → shards). Each has a specific workload where it wins and specific workloads where it fails catastrophically.
The vocabulary
Shard = Partition = Slice — different names for the same concept. Sharding key = partition key = shard column — the value used to decide which shard a row goes to. Rebalancing — moving data when shards fill up or new nodes are added. Hot spot — one shard receiving vastly more traffic than others (the disaster case).
The four strategies
Hash sharding — the industry default
Take the shard key, hash it (Murmur3, CRC32, MD5), modulo by number of shards. Perfect distribution. Simple. Works out of the box for most workloads.
Cost: range queries are dead. You can't SELECT * WHERE created_at BETWEEN X AND Y efficiently — the range hits every shard. You must scatter-gather. This is why Cassandra queries almost always constrain the partition key.
Range sharding — the wrong choice for time-series
Sort keys, split at ranges. Range queries become fast (they hit contiguous shards). But if new writes cluster at the end (like auto-incrementing IDs or timestamps), all writes hit the last shard. The rest of the cluster is idle.
HBase, MongoDB, and DynamoDB (with sort keys) all offer range sharding. Use it only when you know queries will hit contiguous ranges and writes will spread evenly. Time-based IDs almost always violate this.
Consistent hashing — the modern middle ground
Karger et al. (1997). Assign each shard a range on a ring. When a shard is added or removed, only 1/N of the keys move (rather than all of them). Cassandra, DynamoDB, Redis Cluster all use consistent hashing under the hood. See the dedicated concept page for details.
The hot-spot problem
Every sharding strategy has a hot-spot failure mode:
- Hash: one key gets 90% of writes (a celebrity user). Shard containing that hash is overloaded.
- Range: append-only writes to the tail. Time-based data with monotonic IDs.
- Geographic: one region has 60% of your users (bad initial partition).
Choosing a shard key — the checklist
Applied in real systems
Vitess (YouTube-scale MySQL)
Turns MySQL into a sharded database. Used by YouTube, Slack, GitHub. Consistent-hash on user_id typical. Automatic query rewriting for cross-shard.
Citus (Postgres extension)
Turns Postgres into a distributed database. Hash sharding by default. Range for time-series. Now part of Microsoft as Cosmos DB for Postgres.
DynamoDB — hash partitions
Partition key is hashed. Optional sort key gives range queries within a partition. Each partition has a ~1000 write / 3000 read capacity ceiling — hot keys are the enemy.
MongoDB sharding — hash or range
Choose shard key at collection creation. Hash (with hashed index) or range. Config servers hold the map. Automatic balancing (mongos router). Complex to change shard key later.
Cassandra partition key
Compound primary key: partition key (hashed to token) + clustering key (range within partition). Every query must constrain the partition key for efficiency.
CockroachDB — auto range sharding
Table split into 512 MB ranges by primary key. Auto-splits when hot. Auto-rebalances across nodes. Range sharding by default, but interleaved tables + hash sharding available.
Uber Schemaless — sharded MySQL
Uber's wrapper on MySQL, sharded by UUID hash. Trip records, users. Serves millions of QPS across 1000s of MySQL instances. Article on their engineering blog.
Instagram — sharded Postgres
User IDs generated via Snowflake-style, shard-aware. Direct routing to one of ~5000 Postgres instances. Famously wrote about the pattern in 2012.
Key takeaways
- Four strategies: hash (even distribution), range (query-friendly), geographic (compliance), directory (flexible but coordinator-dependent).
- Hash is the default. Range breaks spectacularly on time-series data. Geographic makes multi-region compliance easy.
- Consistent hashing is a specialized hash scheme that limits key movement when shards are added or removed (1/N of keys move, not all).
- Hot spots are the failure mode of every strategy. One celebrity user, one hot key, one popular region.
- Shard key choice is permanent. Almost every database makes it very painful to change the shard key later. Choose carefully.
- Every serious system-design interview will ask about your shard key. Have an answer for hash vs range and know why.
References
- Karger et al. (1997) — Consistent Hashing.
- DeCandia et al. (2007) — Dynamo (consistent hashing).
- Kleppmann (2017) — DDIA, Chapter 6.
- Vitess, Citus, MongoDB, Cassandra docs on partitioning.
Practice what you just read
Every foundation concept has a companion quiz to close the loop.