Skip to content
Navigation

Type at least two characters. Search covers page titles, headings, tags and database names.

↑ ↓ to navigateEnter to openEsc to close0 pages
MongoDBadvanced

MongoDB Sharding

Shard key selection, chunk distribution, the balancer, and the operations that get harder once a collection is sharded.

3 min readAdvancedUpdated Edit this page

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.

Horizontal sharding by key rangeA router or client library hashes the shard key and sends each request to one of three shards. Each shard holds a disjoint subset of the data and has its own replicas, so no single node stores the full dataset.ApplicationShard routerhash(key)Shard Ahash 0x00–0x55Shard Bhash 0x56–0xAAShard Chash 0xAB–0xFF
Horizontal sharding by key range

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.

Key typeDistributionRange queriesNotes
Hashed ({ customerId: "hashed" })EvenBroadcast to all shardsSafe default for point access
Ranged ({ tenantId: 1, createdAt: 1 })Depends on dataTargetedGood when queries filter by the prefix
CompoundControllableTargeted on the prefixUsually the best real-world answer

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 _id within a shard.
  • Queries without the shard key are broadcast to every shard and merged by mongos.
  • $lookup across 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.

Before sharding