On this page
  1. What is sharding?
  2. When sharding is the right answer
  3. The shard key is the whole design
  4. What it costs
  5. Where AI coding assistants get this wrong
  6. Checklist
  7. FAQ
    1. How is sharding different from partitioning?
    2. Do I need sharding for a startup?
    3. What is the biggest risk in sharding?
    4. Can I add shards later without downtime?
  8. Related topics
  9. Sources
concept

What Is Sharding?

Sharding splits one large dataset across several databases so no single machine has to hold it all. It is a last resort, and the shard key is the decision you live with.

Quick answer

  • Sharding partitions rows across multiple database instances, so each holds a subset; the application or a router decides which shard a request goes to.
  • It is horizontal scaling of storage and write throughput, not a way to make a single query faster.
  • The shard key determines everything: it must spread load evenly and be present in almost every query, or requests fan out across all shards.
  • Cross-shard queries and transactions are the costs, and they are the reason to delay sharding until partitioning, indexing, and a bigger machine are exhausted.
  • Resharding later is painful, so choose the key from how the data is queried, not from how it is currently stored.

What is sharding?

It is splitting one logical dataset across several physical databases, each holding a subset of the rows, called a shard. Every row lives on exactly one shard, chosen by a shard key — for example, all rows for a customer on the shard determined by the customer id. A router, which may be in the application or a proxy in front of the databases, uses that key to send each request to the right shard.

This is different from replication, which copies the same data to several machines for read capacity and availability. Sharding divides the data; replication duplicates it. They are often combined — each shard replicated for redundancy — but they solve different problems, and confusing them leads to expecting a read replica to fix a write bottleneck, which it does not.

When sharding is the right answer

Only when a single machine can no longer hold the data or absorb the writes. Before that point, the cheaper answers are a bigger instance, an index that removes the slow query, archiving old rows to a separate store, and read replicas for read-heavy traffic. Each of those is reversible and none changes your application’s structure; sharding changes both.

The signal that sharding is genuinely needed is storage or write throughput approaching the largest instance available, after partitioning and archival. A slow query is not that signal, and neither is a large table that is only large because nothing is ever deleted. Distinguishing those cases is most of the judgement, because sharding is expensive to adopt and much more expensive to undo.

The shard key is the whole design

A good key has three properties: it distributes rows and load evenly, it appears in nearly every query so requests reach one shard, and it is stable, so a row never has to move between shards. Customer id or tenant id usually satisfies all three for a multi-tenant application. A timestamp satisfies none: it concentrates new writes on the newest shard, and queries by user have to search them all.

Hot spots are the failure to watch for. A key with a skewed distribution — one large tenant among many small ones — puts that tenant’s traffic on one shard while the rest idle. Where one key is naturally dominant, a compound key that subdivides it, or routing that tenant to a dedicated shard, is the mitigation. The point is to decide this from the data distribution you actually have, not from the one you expect.

Choosing a shard key — check all three against a real query list:
  [ ] Even distribution: no single value carries a disproportionate share.
  [ ] Present in queries: the common reads and writes include it.
  [ ] Stable: a row never changes shard, so nothing needs moving.
  [ ] Survives growth: still even after the largest tenant grows 10x.

Rejected: created_at (hot spots at the newest shard, every user query fans out).
Typical: tenant_id / customer_id (even, present everywhere, stable).

What it costs

Cross-shard operations become the tax. A query without the shard key must run on every shard and merge the results, which multiplies latency and load by the shard count. A transaction that spans shards needs the coordination patterns discussed elsewhere — sagas or an outbox — because there is no single commit across them. Aggregate reporting, which previously was one query, becomes a fan-out and a merge step that has to be built and maintained.

Operational complexity rises with the shard count. Schema migrations run across every shard and must handle partial failure. Backups, restores, and point-in-time recovery are per-shard, so a consistent restore of the whole dataset is a procedure rather than a command. Capacity planning becomes distribution planning, because the shards are not equally loaded and one of them will fill first. All of this is manageable, and it is the reason the decision is worth deferring.

Where this bites vibecoders

Generated architectures rarely reach for sharding, which is appropriate, but generated code does create the situation that motivates it: unbounded tables with no archival, no indexes, and every row retained forever. The cheaper intervention is usually to index the slow queries and move cold rows out. If sharding does come up, the question to press on is the shard key and whether the common queries contain it — an answer that decides whether the design reduces load or multiplies it.

Where AI coding assistants get this wrong

  • Sharding to fix a slow query that an index would have fixed.
  • Choosing a timestamp as the shard key, concentrating writes on the newest shard.
  • Choosing a key absent from most queries, forcing a fan-out on every request.
  • Planning to reshard later without accounting for the data movement involved.
  • Assuming cross-shard transactions would behave like a single-database transaction.
  • Ignoring a dominant tenant that turns one shard into a hot spot.

Checklist

  • Confirm the limit is storage or write throughput, not a missing index.
  • Try archival, indexing, and a larger instance before sharding.
  • Choose the shard key from the real query list, checking all three properties.
  • Decide how a hot tenant will be handled.
  • Plan for cross-shard queries and transactions explicitly.
  • Document the migration procedure for schema changes across shards.

FAQ

How is sharding different from partitioning?

Partitioning splits a table inside one database, which the engine manages transparently; sharding splits it across separate database instances that the application or a router must target. Partitioning improves manageability and can improve query performance without changing the application’s structure. Sharding changes where the data lives and therefore how the application talks to it.

Do I need sharding for a startup?

Almost certainly not. A single well-indexed instance holds far more than most applications will ever produce, and a read replica covers most read growth. Sharding becomes relevant at storage or write volumes that a single machine cannot serve, which is a problem most products never reach. Reaching that scale is a good problem to solve later.

What is the biggest risk in sharding?

The shard key. A key that does not spread load evenly creates a hot shard that limits the whole system; a key absent from common queries forces every request to fan out; an unstable key means rows must move between shards. Since changing the key later requires migrating all the data, it is the decision to get right up front.

Can I add shards later without downtime?

With care, and it is a significant project. The usual technique is to introduce a routing layer first, so the application stops caring where data lives, then split a shard while routing reads and writes for the moving range. It works, and it is the reason to design the routing layer — and a shard key with room to subdivide — before the first split is needed.

Sources

Share: