Skip to main content

Database Sharding Explained

· 4 min read
Free system design course

A single database server has a hard ceiling — one machine's disk, memory, and CPU. Sharding is how you break past it: split the data across many independent databases instead of scaling one bigger and bigger.

What a shard actually is

A shard is an independent, self-contained piece of a split-up database — its own instance, holding its own subset of the rows, capable of answering queries on its own without talking to any other shard for most operations. Which shard a given row lives on is decided by a shard key: a field on the row (often something like user_id) that gets run through a function to decide its home shard. Every query needs that shard key to know where to even look, which is the first cost sharding imposes: you can no longer just query "the database" — you have to know, or compute, where the data lives.

Range-based sharding

The simplest approach: assign contiguous ranges of the shard key to each shard — user IDs 1–1,000,000 on shard A, 1,000,001–2,000,000 on shard B, and so on. It's easy to reason about and easy to implement, but it has an obvious failure mode: if activity isn't evenly distributed across the key range, some shards end up far hotter than others. A shard holding the newest user IDs in a fast-growing product, or the most active accounts in a range, can become a bottleneck while other shards sit mostly idle.

Hash-based sharding

The alternative: run the shard key through a hash function and use the result to pick a shard. This spreads load far more evenly, since a good hash function doesn't preserve the kind of locality that creates hot spots. The cost is that range queries — "give me all users created this week" — become expensive, since consecutive keys are now scattered across every shard instead of sitting together. Hash-based sharding is typically paired with consistent hashing, which minimizes how much data has to move around when a shard is added or removed.

What sharding costs you

Splitting data across machines doesn't just add operational complexity — it changes what kinds of queries and transactions are even reasonably possible:

  • Cross-shard queries and joins get expensive. A query that needs data from two different shards has to fan out to both and merge results in application code, instead of letting one database engine do it internally.
  • Cross-shard transactions lose easy ACID guarantees. A transaction touching rows on two different shards needs a distributed transaction protocol (like two-phase commit) to stay atomic — meaningfully more complex, and slower, than a transaction that stays on one machine.

This is exactly why choosing a good shard key matters so much: a key that keeps related data — the rows a typical query actually needs together — on the same shard avoids paying this cost on the common path. user_id is a common choice specifically because most queries a product makes are scoped to one user anyway.

Why this matters in an interview

"We'll shard the database" is an incomplete answer on its own. A stronger one names the shard key and defends it (why this key, and why it keeps related data together), names the sharding strategy (range vs. hash, and the hot-spot tradeoff that choice implies), and is upfront about what gets harder as a result — cross-shard joins and transactions specifically. This is often where a strong vs. eventual consistency discussion follows naturally, since sharded systems frequently relax consistency to avoid the cost of coordinating across shards on every write.

Go deeper

The full lesson includes a diagram of how a shard key routes a request to its shard, and walks through the range vs. hash tradeoff in more depth:

👉 Read the full Database Sharding lesson — part of the free System Design Lab course.