Sharding
Partitioning data across multiple databases or nodes to scale writes and storage beyond a single machine.
1. Concept Overview
Sharding splits a dataset into shards (e.g. by user_id or key range), each stored on a different node. It enables horizontal scaling of storage and write throughput.
Why it exists: A single DB has limits on disk, memory, and write capacity. Sharding spreads data and load across many nodes.
2. Core Principles
Shard key choice
Critical: Queries that don’t include the shard key require scatter-gather (all shards) or a separate index.
Balance: Key should distribute data and load evenly (avoid hot shards).
Growth: Prefer keys that don’t create hotspots (e.g. avoid “last N” always in one shard).
Strategies
Hash-based
shard = hash(key) % N
Even distribution
Resharding moves many keys; use consistent hash to reduce
Range-based
Shard 1: A–M, Shard 2: N–Z
Range queries on shard key
Hotspots (e.g. recent data in one shard)
Directory-based
Lookup table: key → shard
Flexible; move individual keys
Lookup table is bottleneck and SPOF
Consistent hash
Ring; key → next node clockwise
Adding/removing node moves ~1/N keys
Implementation complexity
Architecture
3. Real-World Usage
PostgreSQL / MySQL: Application-level sharding (app routes by key); or Citus, Vitess.
MongoDB: Sharding with shard key; config servers hold metadata.
DynamoDB: Partition key (required); optional sort key; automatic sharding.
Kafka: Partitions are shards; key determines partition.
4. Trade-offs
Hash
Even distribution
No range queries across shards; resharding is costly
Range
Range queries on shard key
Risk of hot shards
Directory
Flexible placement
Lookup table scalability and HA
Cross-shard operations
N/A
Joins and transactions across shards are hard; prefer denormalization or application-level join
When to use: Write or storage exceeds single-node capacity; you can design access patterns around shard key. When not: Single node suffices; or you need frequent cross-shard transactions (consider alternatives first).
5. Failure Scenarios
One shard down
Replicate each shard (primary + replica); failover per shard
Hot shard
Choose different shard key; split hot shard (range); or add more replicas for reads
Resharding
Double-write during migration; background data move; consistent hashing to minimize moves
Cross-shard query
Avoid or limit; use caching/denormalization; or accept scatter-gather cost
6. Performance Considerations
Latency: Single-shard queries are fast; scatter-gather increases latency and load.
Throughput: Total write throughput scales with number of shards (if balanced).
Resharding: Expensive; plan for growth so resharding is rare (e.g. consistent hashing with many virtual nodes).
7. Implementation Patterns
Application-managed: App has shard map; routes queries by shard key; uses connection pool per shard.
Proxy: Proxy (e.g. Vitess, ProxySQL) does routing; app sends same query.
Managed (DynamoDB, etc.): Choose partition key; system shards automatically.
Quick Revision
Purpose: Scale writes and storage by partitioning data across nodes.
Shard key: Must be in most queries; should distribute evenly; consider growth.
Strategies: Hash (even), range (range queries, hotspot risk), directory (flexible, lookup cost), consistent hash (minimal resharding).
Cross-shard: Avoid joins/transactions; denormalize or application join.
Interview: “We shard by user_id so each user’s data is on one shard and we can scale by adding shards; we use consistent hashing so adding a node only moves about 1/N of the data.”
Last updated