Chunks, balancer, zones and orphans
How data moves between shards, how to control when it moves, how to pin data to locations with zones, and what orphaned documents are.
- Explain chunks/ranges and the balancer
- Schedule balancing windows and monitor migrations
- Use zones for data locality and tiered storage
- Understand orphaned documents and the range deleter
conceptThe concept
- A chunk (range) is a contiguous range of shard key values on one shard. Default maximum range size is 128 MB (6.0+).
- The balancer runs on the config server primary and migrates ranges to even out data size per shard (6.0+; older versions counted chunks). It also enforces zone rules.
- A migration: the recipient clones the range, catches up with changes, the donor enters a short critical section, metadata is committed on the config servers, and the donor deletes its copy asynchronously.
- Zones map shard key ranges to sets of shards: EU customers on EU shards, recent data on fast storage, a big tenant on dedicated shards.
- Orphaned documents are leftover copies on the donor after a migration (or after an aborted one) until the range deleter removes them. Queries through mongos filter them out.
One migration, step by step
Open the interactive lesson to use this diagram.
whyWhy it matters
Migrations use disk IO, network and cache on both shards. Uncontrolled balancing during peak traffic adds latency. Zones are how you meet data residency requirements with one logical cluster.
Use caseReal-world scenario
A global SaaS shards on { region: 1, tenantId: 1 } with zones EU and IN mapped to shards in Frankfurt and Mumbai, satisfying data residency. The balancer runs only between 01:00 and 05:00 local time; a new shard added before a sales event is filled gradually over several nights.
Try itExamples
Run and edit these in the interactive lesson.
sh.getBalancerState()
sh.isBalancerRunning()
sh.stopBalancer() // before maintenance, backups or upgrades
sh.startBalancer()
// balancing window
db.getSiblingDB("config").settings.updateOne(
{ _id: "balancer" },
{ $set: { activeWindow: { start: "01:00", stop: "05:00" } } },
{ upsert: true })
// recent migrations
db.getSiblingDB("config").changelog.find({ what: /moveChunk|moveRange/ }).sort({ time: -1 }).limit(5)sh.addShardToZone("shard-eu-1", "EU")
sh.addShardToZone("shard-in-1", "IN")
sh.updateZoneKeyRange("shop.customers", { region: "EU", tenantId: MinKey }, { region: "EU", tenantId: MaxKey }, "EU")
sh.updateZoneKeyRange("shop.customers", { region: "IN", tenantId: MinKey }, { region: "IN", tenantId: MaxKey }, "IN")internalsUnder the hood
Since 6.0 the balancer no longer depends on auto-splitting at insert time; ranges are split as needed when they are moved. Migration throttling (_secondaryThrottle, waitForDelete) and concurrency settings trade speed for impact. Direct connections to shard members see orphans unless they use the shard filtering that mongos requests, which is one reason to never read directly from shards.
Avoid / preferDo this, not that
# filesystem snapshot of each shard while the balancer is running
sh.stopBalancer() // take the coordinated backup sh.startBalancer()
A chunk migrating during the backup can be missing from both shards or present on both. Stop the balancer around non-coordinated backups, or use a tool such as PBM that handles it for you.
// at peak traffic, with 30% free disk per shard
db.adminCommand({ reshardCollection: "shop.orders", key: { customerId: 1, createdAt: 1 } })// off-peak, after confirming every shard can hold a full extra copy
db.adminCommand({ reshardCollection: "shop.orders", key: { customerId: 1, createdAt: 1 } })Resharding builds a complete new copy of the collection under the new key, then blocks writes briefly to switch over. Without disk headroom it fails late; at peak it competes with production I/O.
PitfallsCommon mistakes
- Leaving the balancer running during backups that are not balancer-aware, or during upgrades.
- Adding a shard at peak load and expecting instant relief; balancing is gradual.
- Reading directly from shard members and seeing orphaned documents.
- Zone ranges that do not cover the whole key space when you expected them to.
LimitsWhen not to use it
Zones are for placement rules (data residency, hardware tiers), not for evening out load; that is the balancer's job. Do not reach for reshardCollection for a small change: if you only need to add suffix fields to the current key, refineCollectionShardKey changes metadata without copying data.
SecuritySecurity notes
Zones are a compliance control when they keep EU customers on EU shards. Verify placement regularly, and remember residency also applies to backups, logs, analytics copies and support exports, which zones do not cover.
ChallengeTry it yourself
Before creating zones, estimate their size: map each shipping country to a zone (IN, APAC, EU, US, ME) and count orders per zone.
Show one solution
const zoneOf = { India: "IN", Singapore: "APAC", Australia: "APAC", Germany: "EU", UK: "EU", USA: "US", UAE: "ME" }
const rows = db.orders.aggregate([{ $group: { _id: "$shipping.country", orders: { $sum: 1 } } }]).toArray()
const zones = {}
rows.forEach(r => { const z = zoneOf[r._id] || "other"; zones[z] = (zones[z] || 0) + r.orders })
printjson(zones)InterviewQuestions you should be able to answer
What does the balancer do and how do you control its impact?
It moves ranges between shards to keep data evenly distributed and to honour zones. Control impact with a balancing window, stopping it during maintenance, secondary throttle settings, and capacity headroom so migrations do not starve production traffic. Monitor migrations in config.changelog and the logs.
What are orphaned documents?
Copies of documents left on a shard that no longer owns their range, typically after a migration before the range deleter cleans up, or after failed migrations. mongos and shard filtering hide them from normal queries; they matter for direct shard access, storage accounting and some counts.
QuizCheck your understanding
4 questions with instant feedback in the interactive lesson; a wrong answer goes into your review deck.