Database Sharding
Database sharding (horizontal partitioning) is the practice of splitting a large dataset across multiple database instances (shards), where each shard holds a subset of the data and can be hosted on separate machines, enabling horizontal scalability beyond the limits of a single server.
What It Really Means
Every database hits a ceiling. A single PostgreSQL instance can handle perhaps 10,000 writes per second and store a few terabytes before performance degrades. When your application needs 100,000 writes per second or 100 TB of storage, no amount of vertical scaling (bigger server) will help. You need horizontal scaling: split the data across multiple database instances.
Sharding divides rows across databases based on a shard key. All data for shard key "user_123" lives on Shard 3. All data for "user_456" lives on Shard 7. Each shard is a fully independent database that handles only its portion of the data.
The idea is simple. The execution is not. Sharding introduces cross-shard queries, rebalancing challenges, application-level routing, and operational complexity that makes it one of the most impactful (and most feared) scaling decisions an engineering team will make. Instagram, Discord, Pinterest, Slack, and most large-scale systems use sharding.
How It Works in Practice
Sharding Strategies
Hash-based sharding: Apply a hash function to the shard key and mod by the number of shards: shard = hash(user_id) % num_shards. Distributes data evenly but makes range queries impossible.
Range-based sharding: Assign contiguous ranges to shards: Shard 1 handles user_ids 1-1M, Shard 2 handles 1M-2M. Enables range queries but creates hot spots if traffic concentrates on recent data (e.g., all new users hit the last shard).
Directory-based sharding: A lookup service maps each key to its shard. Maximum flexibility but the directory is a single point of failure and a potential bottleneck.
Consistent hashing: Maps keys and shards onto a ring, minimizing data movement when shards are added or removed. Used by DynamoDB, Cassandra, and other distributed databases.
Shard Key Selection
Choosing the right shard key is the most critical decision:
- Good shard key (user_id): Queries for a single user hit one shard. User data is colocated. Even distribution if user_ids are uniformly distributed.
- Bad shard key (country): A few countries (US, India, China) contain most users, creating massive hot shards while others sit idle.
- Bad shard key (created_at): All recent writes hit the same shard (the one for the current time range), creating a write hot spot.
Real-World: Instagram
Instagram sharded PostgreSQL by user_id. Each user's photos, likes, and comments live on the same shard. The shard ID is embedded in each photo's ID using a custom ID generation scheme:
Given a photo ID, you can extract the shard_id without a lookup table. This eliminates the need for a directory service.
Real-World: Discord
Discord stores messages sharded by (channel_id, bucket). Each bucket covers a 10-day window of messages. This means messages in a channel are distributed across time-based shards. Reading recent messages (the common case) hits one shard. Reading old messages (rare) hits a different shard. This optimizes for the read pattern.
Discord migrated from MongoDB to Cassandra (and later ScyllaDB) specifically because of sharding scalability. Their largest guilds generate millions of messages, and time-bucketed sharding prevents any single shard from growing unbounded.
Real-World: Vitess (YouTube)
Vitess is a database clustering system originally built at YouTube to shard MySQL. It provides a middleware layer that makes a cluster of MySQL shards look like a single database. Vitess handles query routing, connection pooling, and online resharding. It powers YouTube, Slack, HubSpot, and many large MySQL deployments.