Fundamentals

Sharding

Picking a shard key, range vs. hash-based sharding, and why resharding is the actual hard problem.

12 minMediumshardingdistributed-systemsfundamentals

Scaling named storage as the hard thing to scale horizontally, because data has to live somewhere and stay findable. Sharding is the specific technique for doing that — splitting one logical dataset across multiple physical databases, each holding a slice of the rows.

Picking a shard key

The shard key is whichever field decides which shard a row lives on. Get it right and most queries hit exactly one shard; get it wrong and most queries have to fan out to every shard and merge results, which erases most of the benefit of sharding in the first place. For a multi-tenant SaaS product, tenant_id is usually the right key — nearly every real query already filters by tenant, so it naturally stays single-shard. For the News Feed case study's Post table, authorId would keep "all of one author's posts" on one shard, which is exactly the access pattern the fan-out-on-write path needs.

Range-based vs. hash-based sharding

Range-basedHash-based
How it assigns shardsContiguous key ranges (A–M on shard 1, N–Z on shard 2)hash(key) % N
StrengthRange queries stay on one shardEven distribution, no hot shards from skewed key ranges
WeaknessA popular range (e.g. usernames starting with a common letter) creates a hot shardA range query ("all users created this week") now has to hit every shard

Most systems default to hash-based sharding specifically to avoid the hot-shard problem — an uneven key distribution in range-based sharding is a common, real failure mode, not a hypothetical one.

Directory-based sharding

A third strategy: instead of computing a shard from a range or a hash, keep an explicit lookup table — a directory — mapping each key (or key range) to the shard that owns it. The win is flexibility: rebalancing a single hot key just means updating one directory entry, no rehashing and no range boundary to redraw. The cost is that the directory itself becomes a new single point of failure and a potential bottleneck — every request pays an extra lookup, and the directory service needs its own redundancy (see Reliability). This is the right trade when shard assignments need to change often or unevenly — moving one unusually large tenant onto its own dedicated shard, for instance — a case hash-based sharding can't express at all, since a key's shard there is a pure function of the key, not an assignment anyone can override.

Resharding is the actual hard problem

Adding a shard to a system using plain hash(key) % N changes N, which changes the shard almost every existing key maps to — effectively re-shuffling the entire dataset at once. This is the problem Consistent Hashing exists to solve, and it's worth naming that connection unprompted: "we'd use consistent hashing specifically so adding a shard doesn't require moving almost everything" is a strong, senior-level line in an interview.

Concretely, a live resharding operation — going from N to N+1 shards without taking the system down — usually looks like: dual-write to both the old and new shard layout for a transition window, backfill the new shards from the old data in the background, verify the backfill caught up, then cut reads over to the new layout and stop writing to the old one. Skipping the dual-write step and doing a single cutover means picking a moment to briefly stop all writes — sometimes an acceptable trade for a small dataset, never acceptable for one that can't tolerate downtime. Naming this sequence, even briefly, is what separates "we'd use consistent hashing" from having actually thought through the migration itself.

Client request

key = user_42

Shard router

hash(user_42) mod N

Shard 2

owns this key's range

Cross-shard queries and joins

A query that needs data from two different shards — a join across tables that live on different shards, or an aggregate across all shards — can't be answered by a single database anymore. The application has to either fan out and merge results itself, or the schema has to be designed to avoid the cross-shard query entirely (denormalizing the data it needs onto a single shard, the same trade-off Database Fundamentals names between normalization and denormalization). Naming which queries a sharding scheme makes hard, not just which ones it makes fast, is usually the difference between a shallow and a strong answer here.