Partitioning and Sharding

Splitting data across many nodes so no single one has to hold or serve all of it, why the partition key decides whether that split is even, and how consistent hashing keeps adding a node from reshuffling everything else.

A single machine has a ceiling: a fixed amount of disk, memory, and network throughput. Partitioning — also called sharding when each partition lives on its own server — raises that ceiling by splitting data across many machines, each responsible for a subset.

The partition key decides everything#

Every row needs a rule that says which partition it belongs to. That rule — the partition key — determines whether load actually spreads evenly or piles onto one node while the others sit idle:

Text
Partition by order_date, one partition per day:
  2026-06-01 -> Partition A  2026-06-02 -> Partition B  2026-06-03 -> Partition C   <- today: every new write lands here
Every write for "today" hits the same partition. The other twopartitions serve reads only — one machine does all the write work.

This is a hot partition: a key choice that is reasonable for one purpose (range queries by date) and disastrous for another (load balancing across writes), on the same data, at the same time.

Range vs. hash partitioning#

Range partitioning keeps keys in order across partitions — everything from A to M on one node, N to Z on another. This makes range scans efficient (fetch three contiguous partitions instead of scattering the read across all of them) and is exactly the pattern that produces hot partitions when the key increases monotonically — a timestamp, an auto-incrementing ID — because every new row's key is always the largest one, always landing on the same node.

Hash partitioning applies a hash function to the key first, then assigns the result to a partition. This spreads writes evenly regardless of whether the underlying key is monotonic, at the cost of range scans: rows that were adjacent by key are now scattered across every partition, so a range query has to touch all of them.

The choice depends on the read pattern, not just the write pattern

A key that spreads writes evenly but forces every query to scan every partition has just moved the bottleneck from writes to reads. Choose the partitioning scheme against the queries the system actually needs to serve well, not only against the goal of even write distribution.

Consistent hashing: adding a node without reshuffling everything#

A naive hash partitioning scheme — partition = hash(key) % N — has a costly property: changing N, by adding or removing one node, changes the result of the modulo for almost every key, forcing nearly all data to move. Consistent hashing avoids this by hashing both keys and nodes onto the same ring and assigning each key to the next node clockwise from it:

Text
Hash ring (simplified, 4 positions shown):
        Node A       /       \  Node D         Node B       \       /        Node C
key "order-42" hashes near Node B -> stored on Node B.Adding Node E between A and B only moves the keys thatwere already between A and B — everyone else is unaffected.

Only the keys between the new node and its counterclockwise neighbor move — roughly 1/N of the data for N nodes, instead of nearly all of it. This is the mechanism behind resizing a cluster without a full data migration every time.

Where this is already in use elsewhere on this site#

ClickHouse MergeTree and Table Design covers PARTITION BY — ClickHouse's own range-style partitioning, chosen coarse specifically to avoid the hot-partition and per-partition-overhead problems this article describes. Topics, Partitions, and Offsets covers a hash-partitioning decision from the other direction: Kafka assigns a message to a partition by hashing its key, for the same load-spreading reason covered above. Neither article names the underlying theory explicitly — this is where it comes from.

Common mistakes#

Partitioning by a monotonically increasing key for write-heavy data#

A timestamp or auto-incrementing ID as the partition key concentrates every new write onto whichever partition currently holds "the latest" — the textbook hot-partition case. Hash the key, or partition on something less correlated with recency, when write throughput matters more than range scans.

Choosing too few partitions#

Too few partitions caps how far the system can actually scale out — with four partitions, a cluster can never usefully run more than four writers in parallel for that data, no matter how many machines are added.

Choosing far more partitions than the cluster can use#

Each partition carries its own overhead — metadata, open file handles, and in the case of ClickHouse's PARTITION BY, a real per-partition storage cost. Partitioning far more finely than the actual node count and query pattern require adds this overhead without a corresponding benefit.

Further reading#

See also#