DATABASES / SYSTEM CONCEPT BRIEF

Sharding

Sharding splits a dataset horizontally across multiple database servers (shards), each holding a subset of rows, so that data volume and write traffic can grow beyond one machine.

AdvancedPhase 04 / Topic 13 of 16RequirementsTrade-offsFailure modes
01

Overview

Sharding splits a dataset horizontally across multiple database servers (shards), each holding a subset of rows, so that data volume and write traffic can grow beyond one machine. A shard key (such as user_id or tenant_id) decides which shard owns each row, and a routing layer sends each query to the right shard.

Sharding is powerful but costly: cross-shard queries, joins, and transactions become hard; resharding when shards fill up requires moving data; and a poor shard key creates hot shards. It is usually the last step after indexing, caching, replicas, and vertical scaling are exhausted.

A library split across branches by surname

Books by authors A-F live in branch 1, G-M in branch 2, and so on. Finding a book by author is quick if you know which branch to visit. Finding every book published in 1999 means visiting every branch.

02

When to use it

  • Write throughput or data size exceeds a single primary.
  • Data naturally partitions by a key (tenant, user, region).
  • Most queries include that key.
  • Isolation between tenants or regions is valuable.
03

Where it shows up in interviews

Scale writes and storage

Recognize it when: billions of rows, heavy write load.

  • Design Twitter's tweet storage
  • Design Instagram photos metadata
  • Design a URL shortener at scale
Multi-tenant SaaS

Recognize it when: many customers of very different sizes.

  • Design Slack's data layer
  • Design a B2B analytics SaaS
04

Where it is used in real software

Instagram

Sharded PostgreSQL by user ID into thousands of logical shards mapped to fewer physical servers, making rebalancing easier.

Vitess

Created at YouTube to shard MySQL transparently; used by Slack, GitHub, and others.

Discord and Notion

Notion sharded PostgreSQL by workspace ID into 480 logical shards as it outgrew a single database.

05

Key terms

Shard key
Column(s) that decide which shard owns a row.
Range sharding
Contiguous key ranges per shard; good for range scans, prone to hot spots.
Hash sharding
hash(key) mod N or consistent hashing; even spread, no range scans.
Directory sharding
A lookup table maps keys to shards; flexible but the directory is critical.
Logical shards
Many small virtual shards mapped to fewer physical nodes, easing rebalancing.
06

How it works, step by step

  1. 1
    Choose the shard key

    High cardinality, even load, present in most queries, and keeps related data together.

  2. 2
    Choose the strategy

    Hash for even spread, range for scans, directory for flexibility.

  3. 3
    Create many logical shards

    For example 1,024 logical shards on 8 servers, so rebalancing moves whole logical shards.

  4. 4
    Route queries

    Application library, proxy (Vitess, ProxySQL), or the database itself (Citus).

  5. 5
    Handle cross-shard needs

    Scatter-gather for rare queries, denormalized global indexes, and sagas instead of distributed transactions.

Hash sharding by user_id
Step 1 / 4
Query user_id=4217
Router
Shard 0
Shard 1
Shard 2
Shard 3

STEP 1The router computes hash(4217) mod 1024 = logical shard 369.

07

Choosing a shard key for a social app

Candidate keys and their effects

Step 1 / 4
Shard keyDistributionQuery localityVerdict
user_id (hashed)EvenUser's own data on one shardGood for profile and posts
created_at (range)All new writes on the latest shardTime-range scans localHot shard: bad for writes
countryVery uneven (large countries)Regional queries localHot spots
post_id (hashed)EvenA user's posts spread everywhereTimeline queries fan out

NOWShard key: user_id (hashed) | Distribution: Even | Query locality: User's own data on one shard | Verdict: Good for profile and posts

The best key matches the dominant access pattern. Celebrities with huge data may still need special handling (splitting or dedicated shards).

08

Implementation

import { createHash } from "node:crypto"; const LOGICAL_SHARDS = 1024;// Mapping of logical shard ranges to physical databases (kept in config or a directory service)const physical = [  { from: 0, to: 255, pool: shardPool0 },  { from: 256, to: 511, pool: shardPool1 },  { from: 512, to: 767, pool: shardPool2 },  { from: 768, to: 1023, pool: shardPool3 },]; function logicalShard(userId: string) {  return createHash("md5").update(userId).digest().readUInt32BE(0) % LOGICAL_SHARDS;} function poolFor(userId: string) {  const shard = logicalShard(userId);  return physical.find((p) => shard >= p.from && shard <= p.to)!.pool;} export const getPosts = (userId: string) =>  poolFor(userId).query("SELECT * FROM posts WHERE user_id = $1 ORDER BY created_at DESC LIMIT 20", [userId]); // Rare cross-shard query: scatter-gather with a limit per shardexport async function recentGlobal(limit = 20) {  const results = await Promise.all(physical.map((p) => p.pool.query("SELECT * FROM posts ORDER BY created_at DESC LIMIT $1", [limit])));  return results.flatMap((r) => r.rows).sort((a, b) => b.created_at - a.created_at).slice(0, limit);}
09

Complexity and performance

Single-shard querySame as unsharded

Routed to one node.

Scatter-gatherO(shards)

Latency = slowest shard.

Capacity~linear with shards

If the key distributes well.

10

Trade-offs

Scale vs complexity

Sharding scales writes and storage nearly linearly but makes joins, transactions, schema changes, and operations harder.

Hash vs range

Hash avoids hot spots but loses range scans; range supports scans but concentrates recent writes.

11

Variants and related techniques

Tenant-based sharding

Each tenant on one shard; big tenants get dedicated shards.

Geo-sharding

Shard by region for data residency and latency.

Auto-sharding databases

MongoDB, Cassandra, DynamoDB, Spanner, and CockroachDB shard and rebalance automatically.

12

Common mistakes

  • Sharding too early.

    Fix: Exhaust indexes, caching, replicas, and vertical scaling first.

  • hash(key) mod N with physical shards.

    Fix: Changing N remaps everything; use logical shards or consistent hashing.

  • Global auto-increment IDs.

    Fix: Use Snowflake-style IDs or UUIDs that embed or allow shard routing.

13

Interview questions

How do you choose a shard key?

Pick a key with high cardinality that spreads load evenly, appears in most queries so they hit a single shard, and keeps data that is queried together on the same shard, such as user_id or tenant_id.

How do you reshard without downtime?

Use many logical shards so moving data means moving whole logical shards. Copy a logical shard to the new server, replicate ongoing changes (CDC), briefly pause writes to switch the mapping, then delete the old copy.

How do you handle queries that do not include the shard key?

Maintain a secondary index or lookup table (for example email to user_id), denormalize into a search system, or scatter-gather for rare admin queries.

14

Practice problems

ProblemDifficultyWhat it trains
Pick shard keys for 4 tables in an e-commerce appMediumLocality.
Design resharding from 4 to 16 serversHardLogical shards and migration.
Design sharding for a multi-tenant SaaS with whalesHardUneven tenants.