hard Sharding Strategies: range vs hash vs directory vs geo
One placement function, one central tension
Sharding maps every row to one of N shards through a placement function shard = f(key). The shape of that function decides one tension that governs everything else: range-query locality vs even load distribution. A function that keeps neighbouring keys together makes ordered scans cheap but concentrates sequential writes; a function that scatters neighbouring keys spreads load evenly but destroys ordered scans. You cannot have both from a single function — picking where you sit on that axis is the core decision, and directory and geo sharding are the two ways to escape the axis by placing data by policy instead of by key shape.
The four strategies, mechanism-first
- Range —
fpreserves key order, so each shard owns a contiguous interval. Neighbouring keys stay physically together, which is exactly what makes ordered scans hit a single shard. The price: a monotonic key (a timestamp, an auto-increment id) sends every new write to the newest shard — a permanent hotspot — and rebalancing means manually splitting/moving intervals. - Hashed —
fscrambles the key (hash(key) mod N), so neighbours scatter and load spreads evenly. But there are no range scans (a range spans all shards), and with naivemod Nthe cluster size is baked into placement: change N and almost every key must move. - Consistent hashing / vnodes — hash both keys and nodes onto one fixed ring; a key belongs to the next node clockwise. Because placement no longer depends on the count of nodes, adding or removing one only reassigns that node's arc (~K/N keys) instead of the whole cluster. Virtual nodes place each physical node at many ring points so arcs stay even and a failed node's load spreads across many successors. This keeps hashing's even load while fixing its elasticity, but still gives up range scans.
- Directory —
fis an explicit lookup table you store and edit, not arithmetic you compute. Placement becomes fully flexible: move one bucket, pin a whale tenant to dedicated hardware, rebalance without a global recompute. The cost is an extra hop on every request, and the directory is a lookup + single point of failure and throughput bottleneck (mitigated by caching and replication — but a stale cached entry silently misroutes). - Geo / by region —
fkeys on location, so rows live in a data centre near their users. This is directory or range sharding with region as the key. It cuts latency and satisfies data-residency law (EU users' data stays in the EU), but any query spanning regions becomes a cross-region scatter, and population skew (one region far larger) unbalances the shards.
Traced example: the same six keys under each strategy
Take six user rows with keys 10, 25, 42, 57, 73, 88 in a key space of 0–99, and N = 3 shards. Watch where each strategy puts them, and what the range query "keys 20–45" costs.
| Strategy | Placement of 10 25 42 57 73 88 | Query "keys 20–45" |
|---|---|---|
| Range [0,33) [33,66) [66,99] | S1: 10, 25 · S2: 42, 57 · S3: 73, 88 | touches S1 + S2 only (contiguous) — no scatter |
| Hash h(key) mod 3 | S0: 25, 73 · S1: 42, 88 · S2: 10, 57 (even 2/2/2) | {25,42} live in S0 and S1, but you can't know which — scatter to all 3 |
| Directory table | whatever the table says — e.g. pin heavy user 88 alone on S3 | range not localized unless the inner scheme is range; extra hop per lookup |
| Geo by region | EU: 10, 42 · US: 25, 57 · APAC: 73, 88 (by user location) | irrelevant unless the query is region-scoped; cross-region = scatter |
The contrast is the whole lesson: under range the query reads two adjacent shards and stops; under hash the same query cannot be localized at all, because hashing deliberately destroyed the ordering the query relies on. Range trades even load for locality; hash trades locality for even load.
Now grow the cluster N=3 → N=4
Under naive hash mod N the divisor changes, so the residue of almost every key changes: roughly (N−1)/N of all rows must move — a near-total migration while serving traffic. Under consistent hashing the new node captures only its ring arc, so only ~K/N keys relocate. This is why elastic hash-sharded stores (Dynamo, Cassandra) use a ring with vnodes, never raw mod N.
Pitfalls
- Range + monotonic key = write hotspot. Timestamps or auto-increment ids drive every insert to the last shard. Salt the key, or hash the write path while keeping a range secondary index.
- Expecting range scans from a hash shard. Hashing scatters by design; an ordered scan becomes a fan-out to every shard. If scans are your money query, do not hash the scan key.
- Raw
hash mod Non an elastic cluster. Growing the cluster copies ~80% of rows. Use consistent hashing with vnodes, or a directory. - Consistent hashing without vnodes. Few nodes → lumpy arcs and skewed load, and a dead node dumps its whole load on one successor. Vnodes are not optional at scale.
- Directory drift / SPOF. A stale cached mapping misroutes reads; an unavailable directory halts them. Cache with invalidation and replicate the directory.
- Geo skew and movers. One dominant region overloads its shards; a user who changes country needs a cross-region data migration and re-consent.
- A single genuinely hot key defeats every hashing scheme. Hashing spreads distinct keys, not one celebrity key — that needs key-splitting or read replicas, not a different
f.
Selection & trade-offs — how a senior engineer decides
Start from the access pattern, not the technique. Two questions settle most of it: do my hot queries scan ranges of the key or look up single keys? and does the cluster grow and shrink often? The first question is the range-vs-hash axis; the second is why naive hash-mod is almost always wrong.
| Strategy | Choose when | Avoid when | Reshard cost | Range scans |
|---|---|---|---|---|
| Range | ordered scans dominate (time-series, dashboards, "last 7 days"); key is non-monotonic | key is monotonic → hotspot | Low — split/merge the affected interval | Excellent |
| Hash (consistent + vnodes) | point lookups on an elastic KV store (user-by-id) | you need ordered scans | Minimal — ~K/N keys move | None |
| Directory | per-tenant / arbitrary placement, whales, uneven shards (multi-tenant SaaS) | extra hop or SPOF unacceptable | Low — remap moved buckets | Depends on inner scheme |
| Geo | data-residency law, latency locality (compliance) | access is heavily cross-region | Migrate a region's data | Within region |
Crisp rules of thumb. Time-series → range (you always scan by time; just avoid a raw monotonic write key). User-by-id / session store → hash (point lookups, elastic membership; you forfeit scans you never needed). Multi-tenant SaaS → directory (you must place tenants by hand and isolate whales; pay for a highly-available lookup layer). Compliance / regional latency → geo (residency is a hard constraint that overrides the axis; accept cross-region scatter). When one axis cannot satisfy residency, elasticity, and locality together, layer them (geo on the outside, consistent hashing inside) and accept the doubled operational surface.
Takeaways
- The central axis is range-query locality vs even load — one placement function cannot give both. Everything else follows from where you sit on it.
- Range wins for ordered scans (time-series) but hotspots on sequential keys; hash wins for even load and point lookups (user-by-id) but has no scans and, if naive, catastrophic resharding.
- Consistent hashing + vnodes keeps hash's even load while cutting reshard movement to ~K/N; it does not buy back range scans.
- Directory (multi-tenant, arbitrary placement, SPOF cost) and geo (compliance, cross-region cost) escape the axis by placing data by policy rather than key shape.
Re-authored for this guide; both diagrams hand-authored as SVG. Sources: Martin Kleppmann, Designing Data-Intensive Applications, ch. 6 (Partitioning); DeCandia et al., Dynamo (SOSP 2007); Karger et al., Consistent Hashing (STOC 1997); Apache Cassandra docs (virtual nodes). See also: Data Sharding Techniques, Online Resharding & Cross-Shard Operations, Consistent Hashing, Shard Key: Hot vs Skew.
🤖 Don't fully get this? Learn it with Claude
Stuck on Sharding Strategies: range vs hash vs directory vs geo? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Sharding Strategies: range vs hash vs directory vs geo** (System Design) and want to truly understand it. Explain Sharding Strategies: range vs hash vs directory vs geo from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Sharding Strategies: range vs hash vs directory vs geo** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Sharding Strategies: range vs hash vs directory vs geo** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Sharding Strategies: range vs hash vs directory vs geo** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.