CMD Guide
HomeSystem DesignData Partitioning

Data Sharding Techniques

A sharding technique is nothing more than a function shard = f(key) that maps every row to one of N partitions; the shape of that function is what decides your three real costs — how much data must move when you add or remove a node (resharding cost), how evenly load spreads (hotspot risk), and whether a query hits one shard or all of them (fan-out). The six techniques below are just different choices of f, and the whole engineering skill is matching that choice to your access pattern.

1. Range-based sharding

Mechanism: the key space is cut into contiguous intervals and each shard owns one interval, so rows that are near each other by key stay physically together — which is exactly what makes ordered scans cheap and range queries hit a single shard.

Worked example. An e-commerce table sharded on order_date:

ShardKey range (order_date)
S12026-01-01 … 2026-03-31
S22026-04-01 … 2026-06-30
S32026-07-01 … 2026-09-30

Query “all orders in May 2026” touches only S2 — no scatter, no merge step. That locality is the entire appeal. The flip side: because order_date only ever increases, every new write lands on the newest shard, so S3 (and whatever succeeds it) is a permanent write hotspot while S1–S2 sit idle. Range sharding rewards range queries and punishes monotonic keys.

2a. Hash-based sharding — the naive version (hash-mod)

Mechanism: compute a hash of the key and take it modulo the shard count — shard = hash(key) % N — so keys are sprayed uniformly and a single-key lookup is O(1) with no directory. The uniformity is real; the trap is the literal N sitting inside the formula.

Worked trace. Eight user IDs, N = 4 shards. (Take hash(id) = id to keep the arithmetic visible.)

user idid % 4 → shardid % 5 → shardafter scaling to N=5
100111stays
100222stays
100333stays
100404moves
100510moves
100621moves
100732moves
100803moves

Adding one shard relocated 5 of 8 keys. This is not bad luck: when the divisor changes from N to N+1, the residue of almost every key changes, so in the general case roughly 1 − 1/(N+1) (~80% for 4→5, rising as N grows) of all rows in the cluster must be re-hashed and physically copied to a different machine.

Why the naive version is wrong: hash-mod bakes the cluster size N into the placement function, so the day you grow the cluster you trigger a near-total data migration while still serving live traffic. Uniform distribution was never the problem — elasticity is. This is the exact pain that motivates consistent hashing, and it is why you should almost never use raw % N in a system expected to scale.

diagram
diagram

2b. Consistent hashing — the fix

Mechanism: hash both the keys and the nodes onto the same fixed ring (say 0…2³²), and a key belongs to the first node found walking clockwise; because node placement no longer depends on the count of nodes, adding or removing one only reassigns the keys in that node's arc — everyone else stays put.

Worked example. Shrink the ring to 0…999 for legibility. Nodes land at A=100, B=400, C=750. Each key goes to the next node clockwise:

key (ring pos)next node clockwise
k1 = 50A (100)
k2 = 250B (400)
k3 = 380B (400)
k4 = 450C (750)
k5 = 820wraps → A (100)

Now add node D at position 500. D only captures keys in the arc (400, 500] — its slice of what used to be C's range. So only k4 (pos 450) moves, from C to D; k1, k2, k3, k5 never budge. One key moved instead of five. In general, adding one node to N moves about K/N keys out of K — the minimum possible.

Virtual nodes (why real systems need them): with only a handful of physical nodes, three random ring positions produce lumpy arcs — one node ends up owning a huge slice. Worse, if a node dies, its entire load dumps onto its single clockwise successor. The fix is to place each physical node at many pseudo-random points (Dynamo/Cassandra use dozens to hundreds of vnodes): arcs even out statistically, and a departing node's load is redistributed across many successors instead of crushing one. This is the difference between the textbook idea and a production-grade ring.

diagram
diagram

3. Directory-based sharding

Mechanism: instead of computing placement, you store it — a lookup service maps each key (or bucket of keys) to a shard, so placement becomes an editable table rather than an arithmetic rule. That indirection buys total freedom: move a single bucket, put a whale tenant on dedicated hardware, or rebalance without any global recompute.

Example. A gaming platform keeps a directory username → shard. A read first hits the directory, then the shard. Onboarding a huge guild? Point just their buckets at a fresh shard and copy only those rows — no rehash of anyone else. The cost: every request pays an extra hop, the directory is a potential SPOF and throughput bottleneck (mitigated by caching + replication), and a stale cached directory entry silently routes reads to the wrong shard. You are trading arithmetic for a table you now have to keep correct and highly available.

4–6. Geographic, dynamic, and hybrid

Geographic: f keys on region, so a user's rows live in a data center near them. Mechanism-wise this is directory or range sharding with location as the key. It cuts latency and satisfies data-residency law (GDPR: EU users' data stays in the EU). Cost: any query that spans regions becomes a cross-region scatter, and a user who moves country needs a data migration.

Dynamic: f is a range map the system rewrites itself — a shard that grows past a threshold or gets hot is split in two, and cold neighbours are merged. This is how HBase region splits and DynamoDB partition splits work in production: no human picks boundaries. Cost: rebalancing consumes I/O, and a sudden write burst can trigger a split storm at the worst moment.

Hybrid: layer the functions — e.g. geo-shard to a region first, then consistent-hash within it. Real large systems are almost always hybrids because no single f satisfies residency, elasticity, and locality at once. It is powerful but multiplies operational surface: two routing layers to reason about, monitor, and debug.

Pitfalls

Selection & trade-offs — how a senior engineer decides

Start from the access pattern, not the technique. The two questions that settle most of it: do my hot queries scan ranges of the key, or look up single keys? and will the cluster grow/shrink often? Range and consistent hashing sit at opposite ends of that first axis.

TechniqueChoose when…Avoid when…Resharding costRange scans
Rangequeries are ordered scans (time-series, dashboards); key is non-monotonickey is monotonic → hotspotLow — split/merge only the affected intervalExcellent
Hash-modfixed N, never scales (rare)any elastic clusterCatastrophic — rehash everythingNone
Consistent hashelastic KV / point lookups (Dynamo, Cassandra, Riak)you need range scans or orderingMinimal — ~K/N keys move per nodeNone
Directoryneed per-tenant / arbitrary placement, uneven shardslookup latency or SPOF unacceptableLow — remap only moved bucketsDepends on inner scheme
Geographicresidency law, latency localityaccess is heavily cross-regionMigrate a region's dataWithin region
Dynamicunpredictable / bursty load, want auto-splityou need stable, predictable placementContinuous, automatic (I/O cost)Range-based → good

Crisp rules of thumb: choose range when your money queries are scans over the key and you can avoid a monotonic key; prefer consistent hashing the moment membership is elastic and access is point lookups — you gain near-free rebalancing but you forfeit ordered scans. Choose a directory when you need to place data by hand (tenants, whales, compliance) and can pay for a highly-available lookup layer; prefer a computed function otherwise to dodge the extra hop and SPOF. Reach for dynamic when load is unpredictable and you'd rather the system rebalance than you; reach for hybrid only when one axis genuinely can't satisfy all constraints, and accept the doubled operational surface.

Takeaways

Drill Ladder — survive the follow-ups

L0 · a sharding scheme is just a placement function f(key) — every follow-up below is really "what breaks when f's assumptions change?"

L1 · ① Concurrency — "reshard a live vnode range while writes keep hitting it — how do you not drop or duplicate rows mid-move?"
Trap: "freeze writes on that range until the copy finishes" — a global stop-the-world pause that becomes a visible outage the moment one range is large or hot.
Bar: dual-write the in-flight range to both old and new owner with idempotent, versioned writes; track a migration cursor per vnode arc; reads consult migration state and prefer the new owner once its copy passes a row-count/checksum parity check, then the old owner stops accepting writes for that arc. online resharding & cross-shard ops

L2 · ② Failure — "the node owning a vnode dies mid-write — what actually serves the next request?"
Trap: "retry on any other replica" — with no ordering guarantee that's a silent consistency violation, not a fix.
Bar: consistent hashing replicates each vnode across N ring-successors (a preference list); on primary failure the coordinator writes to the next live node in that list and records a hint, then replays it via hinted handoff plus read-repair once the original owner recovers. Without vnodes, one successor absorbs 100% of the dead node's load instead of it being spread thin. failover & split-brain fencing

L3 · ③ Adversary/Edge — "one user/key now takes 50x the traffic of any other (celebrity, viral post) — does your hashing scheme absorb it?"
Trap: "add more shards / rehash with a bigger N" — hashing distributes distinct keys; it cannot split one atomic key across nodes no matter how uniform the hash is.
Bar: key-splitting: append a bounded random suffix (key#0..key#9) so the hot logical key becomes N physical sub-keys spread across shards, fan out writes/reads to all suffixes and merge on read (counts sum, feeds fan out); or peel the key onto a dedicated shard/cache tier. This is a data-modeling fix, not a placement-function fix. shard-key skew vs. a single hot key

L4 · ④ Scale — "cluster grows 100x and now every request pays a directory-lookup hop — does the directory itself become the bottleneck?"
Trap: "just replicate the directory service more" — more read replicas don't fix that every rebalance still needs a globally consistent write to the map, and a stale cached entry now misroutes at much higher QPS.
Bar: go hybrid — default placement via a computed function (consistent hash) so most requests need zero lookup, and keep the directory only for the exception list (whale tenants, manual overrides), replicated through a consensus-backed shard-map service and cached at the gateway with a version stamp so staleness is detectable, not silent. request routing & partition discovery

L5 · ⑤ Cost/Simplicity — "PM: directory-based sharding gives full placement control, why not use it everywhere?"
Trap: "sure, maximum flexibility is strictly better" — treating optionality as free.
Bar: directory sharding taxes every single request with a network hop and turns the map into a new HA-critical, consistency-critical service you must build, monitor and fail over — real cost for a guarantee (arbitrary placement) most traffic never needs. Default to a computed scheme (hash/range) that costs zero extra infrastructure, and only layer a directory on top for the handful of keys that genuinely need manual placement. rebalancing strategies beyond consistent hashing

The floor keeps dropping: now make it a multi-row transaction that spans the shards you just rebalanced — a scatter-gather read/write across N shards is bounded below by your slowest shard's p99, and cross-shard atomicity needs 2PC or sagas since single-node ACID is gone the moment the join crosses a shard boundary. Staff+ interviewers will keep composing failures (a node dies during a cross-shard commit) until you either name a concrete protocol or admit the design doesn't support that transaction at all.


Re-authored and deepened for this guide. Sources: Martin Kleppmann, Designing Data-Intensive Applications, ch. 6 (Partitioning); DeCandia et al., Dynamo: Amazon's Highly Available Key-value Store (SOSP 2007); Karger et al., Consistent Hashing and Random Trees (STOC 1997); Apache Cassandra and Apache HBase official documentation on virtual nodes and region splitting.

🤖 Don't fully get this? Learn it with Claude

Stuck on Data Sharding Techniques? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Data Sharding Techniques** (System Design) and want to truly understand it. Explain Data Sharding Techniques 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.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Data Sharding Techniques** 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.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Data Sharding Techniques** 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.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Data Sharding Techniques** 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.

📝 My notes