Separate the sharded cluster into data plane, metadata plane, and stateless routing responsibilities.
Shards as Replica Sets, Config Server Replica Set, mongos Routers, and Metadata
Inspect mongos identity, shard registry, CSRS metadata, and the current MongoDB 8.3 mongos-only DDL boundary.
Learning objectives
Define shard replica sets, the config server replica set (CSRS), mongos routers, and their distinct responsibilities.
Inspect the router identity, shard registry, database primary shard, collection metadata, and range metadata.
Explain why clients should connect through mongos and why direct shard operations are a maintenance exception.
Distinguish a dedicated config server from the MongoDB 8.x config-shard alternative.
Explain how metadata availability affects migrations/DDL differently from ordinary data operations.
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 mandatory
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 router, exposed only on loopback diagnostic
ports 27119–27122. Single-member replica sets satisfy the
mechanism requirement but provide no production redundancy;
production deployments require properly sized multi-member
replica sets and independent failure domains. Authentication and
TLS are disabled only for this isolated local lab. Feature
Compatibility Version (FCV) is observed and never changed.
Reads/writes go through mongos; direct shard
connections are used only for explicitly labeled diagnostics.
The lab intentionally uses a dedicated one-member CSRS instead
of a config shard so the roles remain visually separate. MongoDB
8.x config shards are discussed as an optional architecture, not
required. 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; expected invariants
are documentation-derived and measured timing/output must be
recorded on the learner machine.
1. Four roles, one logical database surface
| Component | Owns | Client responsibility | Production concern |
|---|---|---|---|
| Shard replica set | A subset of sharded collection data plus normal replica-set state. | Do not route normal app traffic directly to a shard. | Replication, elections, storage, indexes, backup, capacity. |
| Config server replica set (CSRS) | Cluster metadata/configuration. | Applications do not query it as business data. | Metadata availability and strict replica-set configuration. |
mongos |
No persistent data; caches routing metadata and merges results. | Application connection endpoint. | Enough routers, network placement, version/FCV compatibility. |
| Config shard (8.x option) | Combines config-server role with application shard data. | Still reached through mongos. | Lower node count but different isolation tradeoffs. |
mongos is intentionally stateless: it caches
cluster metadata from config servers and refreshes when routing
information changes. Each shard still plans and executes its
local portion using its own indexes.
2. Bring up the topology and verify each role
docker rm -f atlasmart-ch16-l2-cfg atlasmart-ch16-l2-s1 atlasmart-ch16-l2-s2 atlasmart-ch16-l2-mongos 2>/dev/null || truedocker network rm atlasmart-ch16-l2-net 2>/dev/null || truedocker volume rm atlasmart-ch16-l2-cfg-data atlasmart-ch16-l2-s1-data atlasmart-ch16-l2-s2-data 2>/dev/null || truedocker network create atlasmart-ch16-l2-netdocker run -d --name atlasmart-ch16-l2-cfg --network atlasmart-ch16-l2-net -p 127.0.0.1:27119:27017 -v atlasmart-ch16-l2-cfg-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --configsvr --replSet atlasmart-cfg16-l2 --bind_ip_alldocker run -d --name atlasmart-ch16-l2-s1 --network atlasmart-ch16-l2-net -p 127.0.0.1:27120:27017 -v atlasmart-ch16-l2-s1-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --shardsvr --replSet atlasmart-shard16-l2-a --bind_ip_alldocker run -d --name atlasmart-ch16-l2-s2 --network atlasmart-ch16-l2-net -p 127.0.0.1:27121:27017 -v atlasmart-ch16-l2-s2-data:/data/db mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --shardsvr --replSet atlasmart-shard16-l2-b --bind_ip_allfor PORT in 27119 27120 27121; 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:27119/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-cfg16-l2",configsvr:true,members:[{_id:0,host:"atlasmart-ch16-l2-cfg:27017"}]})'mongosh "mongodb://127.0.0.1:27120/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-shard16-l2-a",members:[{_id:0,host:"atlasmart-ch16-l2-s1:27017"}]})'mongosh "mongodb://127.0.0.1:27121/admin?directConnection=true" --quiet --eval 'rs.initiate({_id:"atlasmart-shard16-l2-b",members:[{_id:0,host:"atlasmart-ch16-l2-s2:27017"}]})'for PORT in 27119 27120 27121; 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-ch16-l2-mongos --network atlasmart-ch16-l2-net -p 127.0.0.1:27122:27017 --entrypoint mongos mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim --configdb atlasmart-cfg16-l2/atlasmart-ch16-l2-cfg:27017 --bind_ip_all --port 27017until mongosh "mongodb://127.0.0.1:27122/admin" --quiet --eval 'quit(db.runCommand({ping:1}).ok===1?0:1)'; do sleep 1; donemongosh "mongodb://127.0.0.1:27122/admin" --quiet --eval 'printjson(sh.addShard("atlasmart-shard16-l2-a/atlasmart-ch16-l2-s1:27017"));printjson(sh.addShard("atlasmart-shard16-l2-b/atlasmart-ch16-l2-s2:27017"));printjson({hello:db.hello(),shards:db.adminCommand({listShards:1}).shards});'
printjson(db.hello());printjson(db.adminCommand({listShards:1}));sh.status(true);const cfg=db.getSiblingDB("config");printjson(cfg.shards.find().toArray());printjson(cfg.databases.find().toArray());
The router's hello should include
msg:"isdbgrid". The shard registry contains
replica-set connection strings. At this point there may be no
sharded application collection yet.
3. Create a sharded collection and read metadata safely
const app=db.getSiblingDB("atlasmart");app.orders.drop();app.orders.createIndex({tenantId:1,orderId:1});printjson(sh.shardCollection("atlasmart.orders",{tenantId:1}));app.orders.insertMany([ {tenantId:"a",orderId:"a-1",status:"open"}, {tenantId:"n",orderId:"n-1",status:"open"}]);const cfg=db.getSiblingDB("config");const c=cfg.collections.findOne({_id:"atlasmart.orders"});printjson(c);printjson(cfg.chunks.find({uuid:c.uuid},{min:1,max:1,shard:1}).toArray());sh.status(true);
Starting in MongoDB 8.3, DDL operations for sharded clusters
must run through mongos. This lesson therefore
creates indexes/collections/sharding metadata through the
router. Direct shard commands are not a normal application
path.
4. Controlled misuse: connect to a shard directly
echo 'Router identity:'mongosh 'mongodb://127.0.0.1:27122/admin' --quiet --eval 'printjson(db.hello())'echo 'Shard identity (diagnostic only):'mongosh 'mongodb://127.0.0.1:27120/admin?directConnection=true' --quiet --eval 'printjson(db.hello())'echo 'Do not run sharded-cluster DDL or normal app writes through the direct shard connection.'
Direct access bypasses mongos routing and metadata coordination.
MongoDB 8.x restricts direct shard operations; the
maintenance-only directShardOperations privilege
exists for special maintenance cases and carries corruption risk
if misused.
5. Metadata failure is not identical to shard failure
If the CSRS cannot elect a primary, metadata-changing operations such as migrations cannot proceed. Existing data operations may continue in some circumstances because routers and shards already know routing state, but that is not a reason to under-provision config servers. Production uses resilient CSRS members, resilient shard replica sets, multiple routers, authentication, TLS, monitoring, and tested restore procedures.
Treat the config plane and data plane as different failure domains with different signals. Do not put a one-member CSRS or one-member shard into production. A config shard can reduce infrastructure at low shard counts but changes isolation; choose it deliberately. Keep all component binaries/FCV compatible, and route DDL/application traffic through mongos.
Bridge. Lesson 3 uses the metadata you just inspected to explain why some queries target one shard while others scatter to many.
docker rm -f atlasmart-ch16-l2-cfg atlasmart-ch16-l2-s1 atlasmart-ch16-l2-s2 atlasmart-ch16-l2-mongos 2>/dev/null || truedocker volume rm atlasmart-ch16-l2-cfg-data atlasmart-ch16-l2-s1-data atlasmart-ch16-l2-s2-data 2>/dev/null || truedocker network rm atlasmart-ch16-l2-net 2>/dev/null || true
Check your understanding
- What persistent user data does mongos own?
- Where is chunk/range ownership metadata stored?
- Why should applications not connect directly to shards?
- What is a config shard?
Review the answers
1. None. mongos is a router that caches metadata and merges/forwards operations.
2. In the config server replica set, exposed internally through the config database.
3. They bypass routing/metadata coordination and can violate sharded-cluster semantics; direct operations are maintenance exceptions.
4. A MongoDB 8.x option where a replica set serves both config-server and application-shard roles.
Authoritative references
- MongoDB Sharding — Sharded-cluster purpose, chunks/ranges, targeted operations, and architecture.
- Routing with mongos — Router metadata cache, targeted versus broadcast operations, and aggregation routing evidence.
- Config Servers — Config server replica sets, metadata responsibilities, and config-shard alternatives.
-
config Database
— Internal metadata including
config.collections,config.chunks,config.shards, and settings. - sh.status() — Shards, databases, ranges, sharded data distribution, and migration summaries.
- sh.shardCollection() — Shard a collection and define its shard key.
-
sh.addShard()
— Add replica-set shards through
mongos. - Split Chunks/Ranges — Controlled manual split examples and operational cautions.
-
moveRange
— Explicit range migration through
mongos. - Sharded Cluster Balancer — Range migration procedure, thresholds, cleanup, and resource impact.
- MongoDB 8.3 Release Notes — Current 8.3 behavior including mongos-only DDL on sharded clusters.
- mongosh Release Notes — mongosh 2.10.0 baseline.
- PyMongo Release Notes — PyMongo 4.17 baseline.