MongoDB Mastery
MongoDB Mastery lessons / Module 37: Chunks, Balancer & Resharding

Chunks, balancer, zones and orphans

Level 6: Sharding / Distributed25 min

How data moves between shards, how to control when it moves, how to pin data to locations with zones, and what orphaned documents are.

This lesson is interactive. Run every example against an in-browser MongoDB, see explain() plans drawn as trees, and take the quiz.
Open the interactive lesson
You will learn to
  • 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.

Balancer controls
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)
Zones for data residency
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

Avoid
# filesystem snapshot of each shard while the balancer is running
Prefer
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.

Avoid
// at peak traffic, with 30% free disk per shard
db.adminCommand({ reshardCollection: "shop.orders", key: { customerId: 1, createdAt: 1 } })
Prefer
// 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
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.