Prompt 17 · Lesson 04 · Placement policy with zones
Zones and Zone Ranges for Data Locality, Compliance, and Hardware Tiers
Zones constrain eligible shard placement by shard-key ranges. They are powerful for locality and hardware tiers, but they are not authorization or compliance by themselves.
Learning objectives
Define shard zones and zone ranges as placement constraints expressed over the shard key.
Create non-overlapping EU/US ranges on a compound geographic-prefix shard key and inspect the resulting metadata.
Explain inclusive-lower/exclusive-upper zone boundaries and compound shard-key prefix requirements.
Demonstrate a controlled overlapping-zone error and distinguish a zone gap from an overlap.
Explain why zones are not authorization, not a WAN simulator, and not proof of regulatory compliance by themselves.
This lesson pins MongoDB Community Server
8.3.8 with
mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim, mongosh 2.10.0, and PyMongo
4.17.0 where the driver is used. The local topology
is a disposable single-host sharded cluster with one
single-member config server replica set, two
single-member shard replica sets, and one
mongos, exposed only on loopback diagnostic ports
27147–27150. This is sufficient for routing/distribution
mechanics but is not production high availability.
Authentication and TLS are disabled only for the isolated lab.
Feature Compatibility Version (FCV) is inspected in the lab. FCV
is observed and never changed. Application/DDL operations go
through mongos; direct shard connections are
diagnostics only. The two shards are zone-labeled EU/US on one
host. Those labels demonstrate placement rules only; they do not
create physical regions, latency, residency certification, or
independent failure domains. Atlas, Search, Vector Search, KMS,
and Enterprise Advanced are not mandatory. Product commands were
not executed in this generation environment because Docker,
mongod, mongos, mongosh, and PyMongo are unavailable here, so
all timing/load outputs must be measured on the learner machine
rather than copied as invented results.
1. Zones constrain where eligible ranges may live
A zone is a label associated with one or more shards. A zone range associates an inclusive-lower/exclusive-upper shard-key interval with that label. In a balanced cluster, MongoDB keeps ranges covered by a zone on shards associated with that zone. This can represent geographic locality, regulatory placement, or hardware tiers—but MongoDB can enforce only the configured data-placement rule, not the surrounding legal/process controls.
| Rule | Meaning |
|---|---|
| Non-overlap | Zone ranges cannot overlap, even when they belong to different zones. |
| Prefix-aware | For a compound shard key, zone bounds must use shard-key fields and include the needed leading prefix. |
| Gaps allowed | Unzoned key ranges can exist and are balanced normally among eligible shards. |
| Balancer-mediated | Changing zone membership/ranges can trigger migrations; it is not an instantaneous metadata-only placement change. |
docker rm -f atlasmart-ch17-l4-cfg atlasmart-ch17-l4-s1 atlasmart-ch17-l4-s2 atlasmart-ch17-l4-mongos 2>/dev/null || truedocker network rm atlasmart-ch17-l4-net 2>/dev/null || truedocker volume rm atlasmart-ch17-l4-cfg-data atlasmart-ch17-l4-s1-data atlasmart-ch17-l4-s2-data 2>/dev/null || truedocker network create atlasmart-ch17-l4-netdocker run -d --name atlasmart-ch17-l4-cfg --network atlasmart-ch17-l4-net -p 127.0.0.1:27147:27017 -v atlasmart-ch17-l4-cfg-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --configsvr --replSet atlasmart-cfg17-l4 --bind_ip_alldocker run -d --name atlasmart-ch17-l4-s1 --network atlasmart-ch17-l4-net -p 127.0.0.1:27148:27017 -v atlasmart-ch17-l4-s1-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --shardsvr --replSet atlasmart-shard17-l4-a --bind_ip_alldocker run -d --name atlasmart-ch17-l4-s2 --network atlasmart-ch17-l4-net -p 127.0.0.1:27149:27017 -v atlasmart-ch17-l4-s2-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --shardsvr --replSet atlasmart-shard17-l4-b --bind_ip_allfor PORT in 27147 27148 27149; do until mongosh "mongodb://127.0.0.1:$PORT/admin?directConnection=true" --quiet --eval 'quit(db.runCommand({ping:1}).ok===1?0:1)'; do sleep 1; donedonemongosh "mongodb://127.0.0.1:27147/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-cfg17-l4",configsvr:true,members:[{_id:0,host:"atlasmart-ch17-l4-cfg:27017"}]})'mongosh "mongodb://127.0.0.1:27148/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-shard17-l4-a",members:[{_id:0,host:"atlasmart-ch17-l4-s1:27017"}]})'mongosh "mongodb://127.0.0.1:27149/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-shard17-l4-b",members:[{_id:0,host:"atlasmart-ch17-l4-s2:27017"}]})'for PORT in 27147 27148 27149; do until mongosh "mongodb://127.0.0.1:$PORT/admin?directConnection=true" --quiet --eval 'quit(db.hello().isWritablePrimary?0:1)'; do sleep 1; donedonedocker run -d --name atlasmart-ch17-l4-mongos --network atlasmart-ch17-l4-net -p 127.0.0.1:27150:27017 --entrypoint mongos mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --configdb atlasmart-cfg17-l4/atlasmart-ch17-l4-cfg:27017 --bind_ip_all --port 27017until mongosh "mongodb://127.0.0.1:27150/admin" --quiet --eval 'quit(db.runCommand({ping:1}).ok===1?0:1)'; do sleep 1; donemongosh "mongodb://127.0.0.1:27150/admin" --quiet --eval 'printjson(sh.addShard("atlasmart-shard17-l4-a/atlasmart-ch17-l4-s1:27017"));printjson(sh.addShard("atlasmart-shard17-l4-b/atlasmart-ch17-l4-s2:27017"));printjson({hello:db.hello(),fcv:db.runCommand({getParameter:1,featureCompatibilityVersion:1}).featureCompatibilityVersion,shards:db.adminCommand({listShards:1}).shards});'
2. Predefine placement policy before sharding an empty collection
const ns="atlasmart.shipments_zoned";sh.enableSharding("atlasmart", "atlasmart-shard17-l4-a");sh.addShardToZone("atlasmart-shard17-l4-a", "EU");sh.addShardToZone("atlasmart-shard17-l4-b", "US");// Future shard key: {region:1, tenantId:1}. Each range covers every tenant in one region.sh.updateZoneKeyRange(ns,{region:"EU",tenantId:MinKey},{region:"EU",tenantId:MaxKey},"EU");sh.updateZoneKeyRange(ns,{region:"US",tenantId:MinKey},{region:"US",tenantId:MaxKey},"US");const app=db.getSiblingDB("atlasmart");app.shipments_zoned.createIndex({region:1,tenantId:1});printjson(sh.shardCollection(ns,{region:1,tenantId:1}));app.shipments_zoned.insertMany([ {region:"EU",tenantId:"eu-a",shipmentId:"e1"}, {region:"EU",tenantId:"eu-b",shipmentId:"e2"}, {region:"US",tenantId:"us-a",shipmentId:"u1"}, {region:"US",tenantId:"us-b",shipmentId:"u2"}, {region:"APAC",tenantId:"ap-a",shipmentId:"a1"}]);sh.status(true);
Predefining zones on an empty/non-existing namespace lets the initial sharding operation create ranges aligned with zone boundaries. The APAC document deliberately falls in an unzoned gap, so it remains eligible for ordinary balancing; this is a design choice, not an error.
3. Inspect zone membership and range metadata
const cfg=db.getSiblingDB("config");printjson(cfg.shards.find({}, {_id:1,tags:1,host:1}).toArray());printjson(cfg.tags.find({ns:"atlasmart.shipments_zoned"},{ns:1,min:1,max:1,tag:1}).sort({min:1}).toArray());printjson(sh.balancerCollectionStatus("atlasmart.shipments_zoned"));printjson(sh.getShardedDataDistribution());
The config database is internal. Read selected
metadata for diagnosis/learning, but configure zones through
supported commands/helpers rather than directly updating
config.tags or other internal collections.
4. Controlled failure: overlapping ranges are rejected
try { sh.updateZoneKeyRange( "atlasmart.shipments_zoned", {region:"EU",tenantId:"m"}, {region:"EU",tenantId:MaxKey}, "US" );} catch (e) { print(`Expected overlap error: ${e.codeName || e.message}`);}printjson(db.getSiblingDB("config").tags.find({ns:"atlasmart.shipments_zoned"}).toArray());
The EU subrange overlaps the already-declared EU zone range, so MongoDB rejects the conflicting policy. A gap is different: if no zone covers APAC, those ranges are simply not constrained by a zone.
Do not label two containers on the same laptop “EU” and “US” and claim regulatory residency has been reproduced. A production zone plan must map shard members to real failure domains, networks, encryption/security controls, backup placement, operational ownership, and legal requirements.
5. Production judgment
Zone changes can move substantial data. Before changing them, measure affected range bytes, recipient storage/cache headroom, replication lag, migration throughput, and tail latency; schedule balancing windows when appropriate. Design shard keys with future zones in mind because zone ranges can only use shard-key fields and required prefixes. Zones do not grant tenant authorization and do not make a shard highly available.
Bridge. Lesson 5 handles what happens when the current key or distribution is no longer acceptable: refine, reshard, unshard, or move—with explicit preflight and rollback boundaries.
docker rm -f atlasmart-ch17-l4-cfg atlasmart-ch17-l4-s1 atlasmart-ch17-l4-s2 atlasmart-ch17-l4-mongos 2>/dev/null || truedocker volume rm atlasmart-ch17-l4-cfg-data atlasmart-ch17-l4-s1-data atlasmart-ch17-l4-s2-data 2>/dev/null || truedocker network rm atlasmart-ch17-l4-net 2>/dev/null || true
Check your understanding
- Can two zone ranges overlap?
- Can a zone range use any document field?
- What happens to an unzoned APAC range?
- Does a zone prove data residency compliance?
- Why can changing zones hurt latency?
Review the answers
1. No. Zone ranges are non-overlapping and use inclusive lower / exclusive upper bounds.
2. No. It must use shard-key fields; compound-key ranges must include the required leading prefix.
3. It is not constrained by a zone and can be balanced among otherwise eligible shards.
4. No. It enforces configured MongoDB placement; compliance also depends on infrastructure, security, backup, process, and legal controls.
5. It can trigger chunk/range migrations that consume network, I/O, cache, and replication headroom.
Authoritative references
- Choose a Shard Key — Cardinality, frequency, monotonicity, query patterns, and shard-key tradeoffs.
- Troubleshoot Shard Keys — Hot ranges, uneven load, jumbo/indivisible ranges, and scatter/gather symptoms.
- analyzeShardKey — Key-characteristic and sampled read/write-distribution metrics.
- configureQueryAnalyzer — Query sampling for prospective shard-key analysis.
- Hashed Indexes for Sharding — Write distribution and range-query limitations.
- Zones — Zone membership, non-overlapping zone ranges, prefix requirements, and balancing behavior.
- addShardToZone — Associate shards with zone labels.
- Change a Shard Key — Refine versus reshard decision boundary.
- Refine a Shard Key — Append suffix fields without changing existing shard-key field types.
- reshardCollection — Full shard-key change, redistribution phases, demo mode, and abort/commit boundaries.
- unshardCollection — MongoDB 8.0+ consolidation of a sharded collection onto one shard.
- moveCollection — MongoDB 8.0+ relocation of an unsharded collection between shards.
- MongoDB Sharding — Routing, ranges, balancer behavior, and mongos-only client access.
- MongoDB 8.3 Release Notes — Current 8.3 release and sharding/DDL changes.
- mongosh Release Notes — mongosh 2.10.0 baseline.
- PyMongo Release Notes — PyMongo 4.17 baseline.