MongoDB Sharding
Shard key selection, chunk distribution, the balancer, and the operations that get harder once a collection is sharded.
Sharding distributes a collection across several replica sets. It is the only way to scale writes beyond one primary, and the shard key decision is difficult to reverse.
Components
- Shards — each a replica set holding a subset of the data.
- Config servers — a replica set holding the cluster metadata and chunk map.
mongos— the router applications connect to; it consults the metadata and directs queries.
sh.enableSharding("shop");
sh.shardCollection("shop.orders", { customerId: "hashed" });
sh.status();Choosing a shard key
The key must have high cardinality, distribute writes evenly, and appear in the common queries. See Sharding for the general reasoning.
Chunk Distribution
Data is divided into chunks — contiguous ranges of shard key values, 128 MB by default. Chunks split as they grow and are migrated between shards to keep the distribution even.
// Chunks per shard for one collection.
db.getSiblingDB("config").chunks.aggregate([
{ $match: { ns: "shop.orders" } },
{ $group: { _id: "$shard", chunks: { $sum: 1 } } },
{ $sort: { chunks: -1 } }
]);A jumbo chunk is one that cannot be split because all its documents share the same shard key value. It cannot be migrated, so it grows indefinitely and unbalances the cluster permanently. This is the symptom of a low-cardinality shard key, and the fix is a better key — not an operational workaround.
Balancer
The balancer moves chunks between shards to even out the distribution. It runs in the background on the config server primary.
sh.getBalancerState();
sh.isBalancerRunning();
// Restrict balancing to a low-traffic window.
db.getSiblingDB("config").settings.updateOne(
{ _id: "balancer" },
{ $set: { activeWindow: { start: "01:00", stop: "05:00" } } },
{ upsert: true }
);Zones
Zones pin ranges of shard key values to specific shards — used for data residency and for tiering by age.
sh.addShardToZone("shard-eu", "EU");
sh.updateZoneKeyRange("shop.orders", { region: "eu", tenantId: MinKey },
{ region: "eu", tenantId: MaxKey }, "EU");What becomes harder
- Unique indexes are only enforceable if they include the shard key, or on
_idwithin a shard. - Queries without the shard key are broadcast to every shard and merged by
mongos. $lookupacross sharded collections has restrictions and is expensive.- Transactions spanning shards require coordination and are considerably slower.
- Backups must capture all shards plus the config servers at a consistent point; per-shard snapshots taken independently do not restore to one instant.