Shard Keys, Consistent Hashing, Rebalancing & Routing

How to choose a shard key, range vs hash vs directory sharding, hash rings, hot keys, adding a server without moving everything, request routing and…

In this chapter

Placing data on shards: keys, hashing, adding servers and routing

More on Scaling out

Keep learning

Overview

Choosing where each row goes The shard key Range, hash, directory Growing keys Lab: pick a key hash % N vs a ring Hot keys Running it Adding a server Finding the shard Queries without the key Secondary indexes

{NUMBER.get(id)}. {title}

chapters · scaling out Placing data on shards: keys, hashing, adding servers and routing The sharding chapter split one table across several servers. This one answers the practical questions: which server does each row go to, what happens when you add a server, and how does a query find its row? On this page Part 1 · Choosing where each row goes

The shard key: three tests

The shard key is the column whose value picks the server. In the URL shortener it is code: the router hashes the code and gets a shard. You choose it once, at the start. Changing it later means moving almost every row to a new server, so it is the most important decision in sharding. A good key passes three tests. Each test stops one specific failure: What each test protects you from If the key fails it… Example of failing 1. Many distinct values You can never use more shards than the key has values. Extra servers sit empty. is_premium has 2 values, so at most 2 shards, even if you buy 10 servers. 2. Even spread One shard gets most of the data or traffic and becomes the bottleneck (a hot shard). Shard by country with 60% of users in India: one shard holds 60% of everything. 3. In the main query The busiest queries don’t say which shard to ask, so they ask every shard. Shard the shortener by user_id: a click only knows the code, so every click asks all shards.

Scoring some real choices

The shard key is a whole column value, not part of it. For each row, the router takes that value, hashes it, and gets a server. The example row shows which value that would be. Candidate keys, tested Example row (key value in bold) code · URL shortener ✓ good Billions of values, hashes evenly, and every click arrives with the code. user_id · social app Millions of users, and most screens are “this user’s feed, posts, likes”. restaurant_id · food orders ~ usually fine Matches “this restaurant’s orders”, but a few huge chains make their shards busier. Watch them. created_at · any growing table ✕ bad Many values, but every new row has “now”, so all writes land on the newest shard (fails test 2). About 200 values and very uneven (fails tests 1 and 2). Two values, so at most two shards. Fails all three. Rule of thumb: take the key from your most common query (test 3), then check it has many values and spreads evenly (tests 1 and 2).

Range, hash, or directory

Once you have a shard key, you still need a rule that turns a key value into a shard number. There are three. Click each one to see its rule written out, and watch the same six short codes get routed by it. Type your own code to see where it goes. Start with hash. Use a directory only for a specific need, like moving one giant customer onto its own shard.

Growing keys and compound keys

Range-sharded by created_at: every new row is ‘now’, so the last range takes 100% of writes. Auto-increment ids do the same. Key: created_at All new writes hit the last shard. The others sit idle. Key: (sensor_id, created_at) Sensors spread the writes. Each sensor’s readings stay together and in time order. The price: “all readings in the last hour” is now one query per sensor. Hashing only the first part and sorting by the rest inside each shard gives you both.

Lab: pick a shard key for orders

Four shards, the next 1,000 food orders. Try each key and watch for a red bar.

hash % N vs a hash ring

Type a code, switch the method, then add a fourth server and count how many existing codes would have to move. hash % N Simple. Change N from 3 to 4 and about 3/4 of all keys move. Consistent hashing (hash ring)

Hot keys: when one key is too busy

Hashing spreads many keys. It cannot split one: the same key always lands on the same shard. A celebrity, a viral link or a flash-sale item can melt one server. Read-hot: cache it A viral short link is read a million times and written once. Serve it from Redis and replicas. Write-hot: salt it Add a random #0–99 to one hot key so its writes spread over 100 keys. Reads must then merge all 100. Isolate it Move the hot key to a shard of its own (a small directory of exceptions). See it first Watch CPU, p99 and requests per shard, not cluster averages. One shard at 100% hides inside a 30% average. Part 2 · Running it: growth, routing and queries

Adding a server: rebalancing

Your 3 database servers are getting full, so you add a 4th. The new server is empty, so some rows have to move onto it. Every row that moves is copied over the network while the app keeps running, so you want to move as few rows as possible: only the quarter that the new server should own, and nothing else. How many rows move depends on how keys are mapped to servers. Below, 12 orders live on 3 servers. Add a 4th and compare the three methods: the number on each button is how many of the 12 orders have to be copied. The methods in one table How a row finds its server When you add a server Used by hash % N hash(key) % number of servers Most rows move (about 3 in 4) Nobody, at scale Many fixed shards Citus, Elasticsearch, Couchbase Split when big Each shard owns a range of keys or hashes HBase, MongoDB, CockroachDB, DynamoDB Hash ring The new server takes small slices from each of the others Cassandra, ScyllaDB Even a good method copies data, which costs disk and network. Add servers before a known rush (a sale, a final), never during it, and be careful with automatic rebalancing triggered by a server that is only slow, not dead: moving its data onto the others can overload them too.

Finding the shard: routing

The only question is: who holds the map? There are three answers. Pick one and follow the steps: The three choices side by side Who holds the map Not so good The app Fastest: goes straight to the right server Every app must keep its map up to date A front desk (router) One extra stop, and one more thing to run Every server Usually one extra stop Who keeps the map correct? One small, very reliable service holds the one true map (ZooKeeper and etcd are popular ones). Everyone else keeps a copy and is told the moment it changes, for example when a shard moves to a new server.

Queries without the shard key

Links are sharded by code. “Show link 5FTOJ” hits one shard. “All links created by user 42” has no code in it, so every shard must be asked: Shard 1 Shard 2 … Shard 64 links of user 42? no shard key in the query 3 links 0 links 1 link 180 ms: busy with a backup merge → 4 links only after the slowest replies: 180 ms Scatter-gather: ask every shard, wait for all, merge. Choose the key from the main query If most screens are “this user’s …”, shard by user_id instead. Keep a second copy keyed differently A small user_links table sharded by user_id, written alongside each link. Precompute and cache “Top links today” built every minute by a job, not on every request. Accept it when rare An admin report a few times a day may scatter-gather, on replicas.

Secondary indexes: local or global

An index on a column that is not the shard key is either kept per shard (local) or as its own index sharded by that column (global). Local index Writes touch one shard. Reads by the indexed column ask every shard. MongoDB, Cassandra, Elasticsearch. Global index Reads by that column ask one index shard. Writes update several shards and the index can lag. DynamoDB GSIs, CockroachDB, TiDB.

Next

How MySQL, PostgreSQL and other real databases do all this, and the interview answer: sharding in real databases, and in the interview.

More courses

  • Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
  • Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
  • React from open source with patterns — Patterns extracted from Material UI, Radix, React Aria, React Hook Form, Redux Toolkit, TanStack, and Next.js — not slides about hooks.
  • System Design — Core concepts first (SQL vs NoSQL, CAP, indexing, replication, sharding), then designs grouped by what carries them: the database, Redis, Kafka, or many services.
  • Build a real API with NestJS — One ticket-booking API, built in order: a plain Node server first, then NestJS modules, validation, a real database, and the features real clients lean on.
  • Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
  • Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
  • AI engineering for software engineers — Eight free reads, in order, for software engineers moving into AI: when to build an agent, how to build one, how to test it, and how the model works underneath.
  • Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
  • TypeScript in depth — The type system as a design tool. Inference, narrowing, generics, and the errors that mean the model is wrong — not a catalog of utility types.
  • CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
  • Accessibility — Foundations first (WCAG in plain words, semantic HTML, lists, alt text), then hands-on HTML labs, a full pass of WAI-ARIA 1.3, and a final fix-the-page challenge.
  • Docker — What an image is, why layers cache, and how containers find each other on a network.
  • Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.
  • Kubernetes — Kubernetes from zero to operators: why it exists, Pods, Deployments and Services, then configuration, networking, storage, scheduling, scaling and security.