Design Desk

Storage & Data

Database Sharding

Splitting one database that's run out of room to grow into many smaller ones, and why the one decision that matters is the key you split it on.

Storage & DataAdvanced6 min readPrerequisites: Caching, Databases (SQL vs NoSQL)

After this lesson, you should be able to:

  • Explain what a shard key does and why its choice, not the number of shards, is the decision that matters.
  • Distinguish a natural key from a hashed key for shard distribution, and the query-locality-versus-even-distribution trade-off between them.
  • Diagnose a hot-shard problem: a key that's evenly distributed by schema but not by real-world traffic.
  • Explain why resharding is expensive under a hashed key and comparatively straightforward under a natural key.

At a Glance

  • Sharding splits one database across multiple machines by a shard key, so no single machine has to hold or write all the data.
  • Caching and read replicas both assume the write path still fits on one primary. Sharding is what you reach for once that assumption breaks.
  • The shard key is the whole decision: pick it wrong and you get a hot shard carrying most of the load, or a common query that has to fan out across every shard to get one answer.

01 The Problem

A food-delivery platform's orders table has grown to 2 billion rows. Reads are already cached, and read replicas handle reporting queries, but every new order is still a write to the same single primary, and that primary is now the bottleneck: write throughput is capped by one machine's disk I/O, and the table is too large for routine maintenance to run without measurable write stalls. Caching didn't help, because writes were never the problem it solves. Read replicas didn't help either, because they don't accept writes at all. The only way to add more write capacity is to stop asking one machine to hold all the data.

So the data gets split across many databases, by some key. Split by restaurant_id, and the day a large national chain launches, a huge share of all new orders route to that one chain's shard while the rest sit nearly idle, a hot shard. Split by a hashed, evenly-distributed key instead, and the hot-shard problem goes away, but now "show me this customer's order history," a routine, constant query, has no single shard to go to. Their orders are scattered evenly across every machine, so answering it means asking all of them and merging the results.

Neither is free. Pick the key wrong and either your machines carry uneven load, or your everyday queries can't be answered by touching just one of them. This is sharding.

02 What It Is

Sharding, or horizontal partitioning, splits a single logical dataset across multiple independent database instances, shards, where each shard holds a subset of the rows. A shard key, one field or a combination, decides which shard a given row lives on. That's the difference from a read replica: a replica is a full copy of everything, used only for reads. A shard holds a portion of the data, and accepts writes for that portion.

The infrastructure of running many databases instead of one isn't really the hard part, that's mostly repetition: the same schema, spun up N times. The hard part is choosing the shard key before you fully know your access patterns, because changing it later means physically moving rows between machines while the system stays up and serving traffic, one of the more unforgiving migrations in backend engineering.

In Plain Terms

A library splits its collection across several buildings to fit more books than one building has shelf space for. Split by author's last name, and a request for "everything by this one author" is a single trip to a single building, but if one author turns out to be wildly more popular than the rest, that building gets crowded while the others sit empty. Split by a random accession number instead, and crowding stops being a problem, but now "everything by this author" means checking every building, because their books ended up scattered across all of them by chance.

03 How It Works

Rendering diagram…

A write and a later query for the same customer hash to the same shard, so the read never has to guess which machine to ask.

Try it: leave the strategy on Natural Key and route a few obvious customer IDs, 1, 42, 100, they all land on the same shard. Switch to Hashed Key and send the same IDs again, they spread across all four. Then click Query Without Shard Key to see why that query pays a different cost entirely, regardless of which strategy is selected.

Shard key strategy

Shard 1

0

rows

Shard 2

0

rows

Shard 3

0

rows

Shard 4

0

rows

No writes routed yet.

04 Trade-offs

 Natural key (e.g. customer_id)Hashed key (e.g. hash of order_id)
Load distributionUneven if the real world isn't evenly distributed: one huge customer becomes a hot shardEven by construction, a hash spreads rows uniformly regardless of who or what they belong to
Common queriesA customer's full history lives on one shard, fast and simpleA customer's history is scattered across every shard, needs a fan-out and merge
ReshardingRebalancing moves one customer's data as a unit, straightforward to reason aboutRebalancing means recomputing hash ranges and moving arbitrary slices of unrelated rows
Best forAccess patterns almost always scoped to one entity, per-customer, per-tenantWrite-heavy workloads where even distribution matters more than query locality

Watch out

It's tempting to treat sharding as a purely infrastructure problem: add more database servers, spread the data, done. The infrastructure is the easy part. The shard key is a decision about your application's actual query patterns, made in advance, and getting it wrong doesn't show up as an outage on day one. It shows up months later, as one specific shard mysteriously running hot, or one report query that used to take a second suddenly touching every machine you own.

05 Where You'll Actually See This

The URL shortener case study is a useful contrast: its own estimation section sizes the dataset at 1 billion URLs, roughly 500GB in a single Postgres primary, and calls that unremarkable. That's not an oversight, it's the point: at that scale, sharding isn't needed yet. This article covers what happens once the math changes, more writes than one primary can absorb, not more storage than one disk can hold.

It also connects two things covered elsewhere. Caching absorbs read load, but it was never going to help here, a cache sits in front of reads, and the write in this scenario still lands on a single primary either way. Sharding is what you reach for once the bottleneck is writes, not reads, and caching has nothing left to give. SQL vs NoSQL already names this pattern without explaining it: a NoSQL store "built to shard writes across many machines from the start" is describing exactly the mechanism this article walks through, just built into the database instead of built by hand.

Database indexes solve a different problem entirely, worth naming because the two get confused: a shard key spreads write load across machines, it doesn't make a lookup within one shard any faster. An index does that, and a shard with no index on the columns it's queried by is still doing a full scan, just a full scan of a smaller table.

How to reason about it

When asked how you'd shard a system, don't start with the infrastructure, however many machines, however replication works. Start with the shard key: name the field, say why it distributes load evenly for this specific workload, and say which of your common queries no longer fit on one shard once you pick it. If you can't name that last cost, you haven't chosen a shard key, you've picked a number of database servers.

06 Quick Check

A team shards their orders table by restaurant_id to spread write load evenly. A single national fast-food chain then onboards, and nearly a third of all new orders route to that one chain's shard. What actually went wrong?