Skip to content
Discovery Databases 4 min read · Updated 6 Aug 2026

Sharding vs Partitioning vs Replication

advanced databasesscalingpostgres

These three words get used interchangeably in architecture discussions, and they solve completely different problems. Getting them confused leads teams to shard when they had a read problem, which is an expensive way to make things worse.

The distinction

Replication — the same data, copied to more machines. Solves read capacity and availability. Every replica holds everything, so writes still go to one primary and the write ceiling is unchanged.

Partitioning — one table, split into pieces, inside one database. Solves unwieldy tables: enormous indexes, slow bulk deletes, vacuum pressure. The database still plans and executes queries as a single system, so joins, transactions and foreign keys all still work.

Sharding — data split across separate databases. Solves write capacity and dataset size. Nothing coordinates them by default, so the guarantees you took for granted stop applying.

The ladder matters: replication and partitioning keep you inside one database’s guarantees. Sharding leaves them.

Partitioning, which is usually enough

Postgres declarative partitioning splits by range, list or hash:

CREATE TABLE events (
  id bigserial,
  occurred_at timestamptz NOT NULL,
  payload jsonb
) PARTITION BY RANGE (occurred_at);

CREATE TABLE events_2026_08 PARTITION OF events
  FOR VALUES FROM ('2026-08-01') TO ('2026-09-01');

Two real wins:

Partition pruning. A query filtering on occurred_at touches only the relevant partitions. Smaller indexes, less I/O.

Instant data lifecycle. DROP TABLE events_2026_02 removes a month in milliseconds. The equivalent DELETE writes to the WAL, bloats the table and leaves vacuum to clean up for hours.

The catch is that the benefit only exists when queries filter on the partition key. Partition by month and then query by user_id and you scan every partition — strictly worse than the unpartitioned table.

Sharding, and what it costs

Sharding is not a database feature you switch on. It is an architectural change that removes guarantees.

Cross-shard joins stop existing. Two tables on two machines cannot be joined by the database. You fetch from both and join in application code — no planner, no index-assisted merge, and a lot of manual work.

Cross-shard transactions stop being atomic. Writing to two shards is two independent transactions. One can commit while the other fails. Either you adopt two-phase commit, or the saga pattern, or you design so it never happens.

Unique constraints stop being global. The database can only enforce uniqueness within one shard. Globally unique values need a separate authority — which is one of the strongest arguments for UUIDv7 or ULID keys, since they need no coordination.

Rebalancing is a project. Adding shards means moving data while serving traffic. Consistent hashing or a lookup table of key ranges reduces the pain; modulo-based routing (hash(id) % shard_count) means adding a shard remaps nearly everything, so avoid it from day one.

Choosing the shard key

This is the decision you cannot cheaply undo. Three requirements, and they pull against each other:

It appears in almost every query. Otherwise requests must fan out to all shards and you have built a slower database. In multi-tenant systems tenant_id is usually right — nearly every query is already scoped to one tenant.

It distributes evenly. Sharding by country puts your largest market on one machine. Sharding by tenant works until one customer is fifty times bigger than the rest, which is the normal shape of B2B revenue.

It rarely changes. Changing a row’s shard key means moving the row between databases.

Common good keys: tenant_id, customer_id, user_id. Common bad keys: timestamps (all writes land on the newest shard), auto-increment ids (same), low-cardinality categories.

Try these first, in this order

Sharding is the last step, not an early one. Most teams that shard did not need to:

  1. Index properly. A missing index can cost more than a machine. Start here.
  2. Fix N+1 queries. Often the entire “database is slow” problem. Here.
  3. Right-size the connection pool. More connections is usually slower. Here.
  4. Cache. Read pressure is what caches exist for.
  5. Read replicas. Reads are almost always the majority.
  6. Vertical scaling. A modern single instance handles far more than people assume, and the price of a bigger machine is trivially cheaper than a distributed-systems project.
  7. Partition the tables that have genuinely become unwieldy.
  8. Then consider sharding.

If your bottleneck is reads, sharding is the wrong tool entirely — you want replicas and caching, and sharding will add complexity without touching the constraint.

What you have actually chosen

Whether the database remains one system that can reason about all your data.

Replication and partitioning keep that property. Sharding trades it away for write throughput, and everything you lose — joins, atomic multi-row writes, global constraints — you rebuild by hand, in application code, forever.

Sometimes that trade is correct and unavoidable. It should never be the first thing tried, and it should never be reached for because it is what large companies do. They shard because they exhausted the list above. Most systems never get there.

Quick answers

What is the difference between sharding and partitioning?
Partitioning splits a table into pieces inside a single database, which still plans and executes queries as one system. Sharding splits data across separate independent databases, so the application or a proxy must decide where each query goes and cross-shard operations lose ACID guarantees.
When should I shard my database?
When write throughput or dataset size genuinely exceeds one machine and you have already exhausted indexing, caching, read replicas, connection pooling and vertical scaling. Sharding is the most expensive scaling step and the hardest to reverse.
How do I choose a shard key?
Pick the value that appears in the overwhelming majority of your queries — often tenant or customer id — so most requests hit one shard. It must also distribute evenly; a key that concentrates your largest customers on one shard recreates the bottleneck you were escaping.
Does partitioning make queries faster?
Only when the planner can eliminate partitions using the partition key, or when it lets you drop old data instantly instead of running a large DELETE. A query that does not filter on the partition key may get slower, because it must scan every partition.

References

Related Discoveries