FullStack Course LogoFullStack Course
Module: System Design
System Design·258·11 MIN READ

258: Partitioning and Sharding: Keys, Rebalancing, Routing, and Hotspots

TOPICS COVERED: Partitioning and Sharding: Keys, Rebalancing, Routing, and Hotspots

Learning outcomes

By the end of this lesson, you should be able to:

  • explain and apply horizontal partitioning in a realistic implementation;
  • explain and apply range sharding in a realistic implementation;
  • explain and apply hash sharding in a realistic implementation;
  • explain and apply consistent hashing in a realistic implementation;
  • explain and apply rebalancing in a realistic implementation.

Prerequisites and retrieval

This lesson builds on the earlier 01–06 foundation and the preceding lessons in this module. Before you start, retrieve one concrete example from a previous project where this kind of scaling concern appeared. It might have been a database that was approaching its capacity limit, a cache whose keys needed to be distributed, or a query that became expensive as the dataset grew.

The point is not to memorize a collection of terms. The point is to make a defensible choice for a large-scale distributed service. That choice depends on explicit requirements, traffic shape, failure modes, cost, and operational constraints.

Terminology

  • Horizontal partitioning: Splitting rows or documents by a key range, hash, or directory so that each shard owns only a subset of the data.
  • Range sharding: Assigning contiguous key ranges to shards. This preserves ordered locality and makes range scans efficient, but monotonically increasing keys or an uneven distribution can concentrate traffic on one shard.
  • Hash sharding: Hashing a key before selecting a shard. This generally spreads keys more evenly, but it removes natural range locality and makes resharding difficult unless an indirection layer or a consistent-hashing scheme is used.
  • Consistent hashing: Using a ring and often virtual nodes to limit how many keys move when the node set changes. It is common in distributed caches and stores, although replication and unequal node capacity introduce additional design details.
  • Rebalancing: Moving data between shards when ownership or capacity changes. The transfer consumes network and I/O resources and can affect request latency.
  • Cross-shard operations: Joins, transactions, unique constraints, and aggregates that span shards. These operations are harder to coordinate and usually cost more than operations confined to one shard.

Mental model

Treat Partitioning and Sharding: Keys, Rebalancing, Routing, and Hotspots as a design problem with observable inputs, outputs, invariants, and failure modes. Sharding divides a dataset and its workload across nodes, allowing capacity to scale horizontally. The cost is additional coordination: cross-shard operations become more complicated, data has to move during rebalancing, and a poor key can still create a hotspot. That complexity should be justified by actual scale rather than added pre-emptively.

A strong implementation makes its assumptions visible, reduces uncertainty at system boundaries, and leaves evidence that the design is safe. That evidence might be tests, types, database constraints, routing metrics, ownership/version metadata, or diagrams.

For an interview or a production design, use this sequence:

text
requirement -> constraints -> model -> implementation -> failure analysis -> verification

Do not jump from a requirement straight to a library call. First state what must remain true. Then select the mechanism that enforces that invariant, and finally decide how you will observe failures when the mechanism is under load or during a topology change.

Deep dive

1. Horizontal partitioning

The basic move is to split rows or documents by a key range, a hash, or a directory so that every shard owns a subset of the dataset. The partition function is part of the system contract: it must be stable enough that the same key can be routed consistently, and it must be discoverable by the component handling the request.

Horizontal partitioning is worth introducing when it makes a capacity or ownership invariant easier to maintain. If it only hides an assumption behind a helper or reduces a few lines of application code, the extra operational machinery is probably not justified. Keep the routing rule explicit enough to inspect and test.

2. Range sharding

Range sharding assigns contiguous portions of the key space to different shards. Because nearby keys remain together, queries such as “all orders created between these two timestamps” can often be served efficiently. The same locality can become a weakness: writes for monotonically increasing keys tend to land in the newest range, and an uneven customer or timestamp distribution can overload one shard while others are mostly idle.

Choose range sharding when ordered locality and range scans matter more than perfectly even distribution. The trade-off should be visible in the design, along with a plan for splitting a hot or oversized range.

3. Hash sharding

Hash sharding hashes the partition key before choosing a shard. This usually distributes individual keys more evenly and avoids the obvious “all new writes go to the last range” problem. In return, the hash destroys natural ordering: a range query may need to contact every shard. Changing the shard count can also remap a large portion of the key space, so resharding is difficult without an indirection layer or consistent hashing.

Choose hash sharding when balanced point-key distribution is the main requirement and range locality is not central to the workload. Verify that the selected key has enough cardinality and that the system has a migration strategy before changing the shard topology.

4. Consistent hashing

Consistent hashing places nodes, often represented by multiple virtual nodes, on a logical ring. A key is hashed onto that ring and assigned to the next eligible node. When a node is added or removed, only the ranges adjacent to the topology change need to move in the idealized model, rather than every key being remapped.

This reduces movement, but it does not make rebalancing free or automatically solve hotspots. Replicas, virtual-node counts, node weights, failure handling, and ownership metadata all affect the practical result. Use consistent hashing when membership changes and limited key movement matter, especially in distributed caches or stores, and measure whether the resulting ownership is actually balanced.

5. Rebalancing

Rebalancing moves data after a shard is added, removed, split, or found to be overloaded. The transfer competes with normal traffic for network bandwidth and storage I/O, so it can increase latency even when all requests are logically correct.

Online rebalancing needs an explicit ownership and version transition. During the handoff, readers and writers must know which owner is authoritative, how to handle an in-flight request, and how to avoid losing or duplicating data. A routing table that changes without a coordinated migration protocol is not a complete rebalancing design.

6. Cross-shard operations

Once related records live on different shards, joins, transactions, global uniqueness checks, and aggregates need coordination across those boundaries. They may require fan-out queries, a coordinator, an asynchronous workflow, or a different data model, each with its own latency and consistency trade-offs.

Co-locate data that regularly participates in the same atomic or relational workflow whenever possible. That does not eliminate every cross-shard operation, but it keeps the common path simpler and makes the exceptional distributed operation easier to identify and monitor.

Worked example

Consider a large-scale distributed service whose requirements, traffic patterns, failure modes, cost limits, and operational constraints still need to be made explicit. Start with a one-sentence requirement. Then write the input and output contracts and identify which of the concepts above owns each failure mode.

The useful separation is by responsibility: parsing and boundary validation belong at the boundary; domain rules belong in the domain or service layer; persistence rules belong in the database or repository; and presentation rules belong in the client. Mixing these concerns can make a happy-path demo look shorter, but it makes routing errors, malformed data, retries, and partial failures much harder to reason about.

text
Client
  |
DNS -> CDN / Edge
  |
Load Balancer -> API instances -> Cache
                         |          |
                         +------> Primary datastore
                         |
                         +------> Queue / Stream -> Workers

Walk through at least four cases: the normal request, an empty or missing value, a duplicate/retry/concurrent request where that applies, and a dependency failure. For every case, state which layer detects the problem and what the caller observes. For a sharded service, also state how the request is routed, whether it stays on one shard, and what happens if the routing metadata is stale. That level of detail is what a senior code review or technical interview should expose.

Production perspective

Production correctness means more than “the code works on my machine.” Ask how the design behaves during deployments, retries, partial failures, stale clients, concurrent requests, malformed data, schema changes, and high-cardinality traffic. Prefer explicit contracts, bounded resource usage, structured errors, and measurable behavior. Do not optimize a partitioning scheme until you can point to the bottleneck or risk in metrics, traces, query plans, or representative load tests.

When the design calls an external dependency, define both a timeout and a cancellation strategy. When it persists data, define its transaction and consistency expectations. When it exposes user-visible state, account for loading, empty, error, stale, and success states. When it has a security boundary, assume the client can be modified and every network input is untrusted. Sharding changes placement; it does not replace authorization, validation, or recovery guarantees.

Guided lab

Choose and defend a shard key for orders or messages. Simulate 10× user growth, one celebrity or hot account, and the addition of shards. Explain the routing decision, how rebalancing moves ownership, and how a cross-shard query is affected.

Complete the lab with this discipline:

  1. Write the requirement and two non-requirements.
  2. List the input, output, and error contracts before implementation.
  3. Implement the smallest correct vertical slice.
  4. Add at least one invalid-input test and one edge-case test.
  5. Instrument or inspect the behavior instead of guessing.
  6. Refactor one hidden assumption into an explicit type, constraint, function, or configuration.
  7. Explain one alternative design and why you did not choose it.
  8. Record a short “what would break at 10× scale?” note.

For the hot-account case, do not stop at saying that the hash is uniform. Ask whether the account itself receives enough traffic to overload its assigned shard, whether writes can be split safely, and whether the resulting read or aggregation path remains correct.

Edge cases and failure modes

  • Horizontal partitioning: Test absent and malformed keys, duplicate requests, ordering and concurrency where applicable, and behavior at the smallest and largest credible sizes. Verify that the same valid key maps to the expected owner after a routing-table refresh.
  • Range sharding: Test absent and malformed boundaries, duplicate requests, ordering and concurrency where applicable, and the smallest and largest credible ranges. Include a monotonically increasing workload and an uneven distribution that forces a range split or exposes a hotspot.
  • Hash sharding: Test absent and malformed keys, duplicate requests, ordering and concurrency where applicable, and the smallest and largest credible dataset sizes. Check how point lookups and range queries behave, and measure the remapping impact of changing the shard count.
  • Consistent hashing: Test absent and malformed node or key data, duplicate requests, ordering and concurrency where applicable, and the smallest and largest credible node sets. Add and remove nodes, inspect key movement, and verify replica and weight behavior rather than assuming the ring is balanced.
  • Rebalancing: Test absent or stale ownership metadata, malformed migration records, duplicate transfers, ordering and concurrency where applicable, and the smallest and largest credible migrations. Verify reads and writes during handoff, retries, interruption, resumption, and the final no-loss/no-duplication state.

Common mistakes and debugging

  • Solving the example instead of the requirement: a copied partitioning pattern can be syntactically correct while being architecturally wrong for the workload.
  • Hiding uncertainty with assertions, broad exception handlers, permissive schemas, or “temporary” any values.
  • Testing only the happy path and discovering the actual routing and ownership contracts only during integration.
  • Optimizing before measuring, or choosing a scalable mechanism when no scale requirement justifies its operational cost.
  • Treating client-side behavior as a substitute for server-side authorization, validation, or persistence guarantees.

When debugging, reproduce the smallest failing case first. Inspect the actual key, routing decision, ownership version, and execution plan instead of inferring them from the final error. Trace the boundary where the invariant first becomes false: source or build, browser or DOM, Network or HTTP, server or route, database or query, or deployment or configuration. Then fix the layer that owns the invariant rather than adding a downstream patch that only masks the symptom.

Interview questions

  1. What problem does Horizontal partitioning solve, and what trade-off or failure mode would make you choose a different approach?
  2. What problem does Range sharding solve, and what trade-off or failure mode would make you choose a different approach?
  3. What problem does Hash sharding solve, and what trade-off or failure mode would make you choose a different approach?
  4. What problem does Consistent hashing solve, and what trade-off or failure mode would make you choose a different approach?
  5. What problem does Rebalancing solve, and what trade-off or failure mode would make you choose a different approach?

Checkpoint

Without notes, explain Partitioning and Sharding: Keys, Rebalancing, Routing, and Hotspots to another developer in five minutes. Include one invariant, one edge case, one production failure mode, and one alternative design. Then implement a small example without copying the lesson code.

Mastery checklist

  • I can define the core terms precisely.
  • I can choose a design from requirements instead of from habit.
  • I can implement and test the normal path and edge cases.
  • I can explain the runtime, storage, or complexity cost.
  • I can identify which layer owns validation, errors, and recovery.
  • I can compare at least two reasonable alternatives.
  • I can explain how the design changes at larger scale or stricter reliability.

References

Reader page: /system-design/lesson/258/partitioning-and-sharding-keys-rebalancing-routing-and-hotspots