Sharding
MongoDB sharding: partition data across shards by shard key. Routers, config servers, and the trade-offs at scale.
MongoDB — sharding
EXAMPLE
# ===== When to shard =====
# - Working set > single node RAM
# - Write throughput exceeds one primary
# - Need geographic data isolation (regional shards)
# Otherwise: replica set is enough.
# ===== Architecture =====
# - Config servers (3-node replica set): store metadata
# - Shards (each a replica set): store actual data
# - mongos routers: stateless query routers; apps connect to them
# Client -> mongos -> shard(s) -> response
# ===== Setup outline =====
# 1. Start config server replica set
mongod --configsvr --replSet cs --port 27019 --dbpath ./cfg
mongosh --port 27019
> rs.initiate({ _id: 'cs', configsvr: true, members: [{ _id: 0, host: 'cfg1:27019' }, ...] })
# 2. Start shard replica sets (per shard)
mongod --shardsvr --replSet shard0 --port 27018 --dbpath ./s0
> rs.initiate({ _id: 'shard0', members: [{ _id: 0, host: 's0a:27018' }, ...] })
# 3. Start mongos
mongos --configdb cs/cfg1:27019,cfg2:27019,cfg3:27019 --port 27017
# 4. Add shards to the cluster
mongosh --port 27017
> sh.addShard('shard0/s0a:27018,s0b:27018,s0c:27018')
> sh.addShard('shard1/s1a:27018,...')
# ===== Enable sharding =====
sh.enableSharding('shop')
sh.shardCollection('shop.orders', { customer_id: 'hashed' })
# ===== Shard key choice (the most important decision) =====
# Good shard keys have:
# - HIGH CARDINALITY (many distinct values)
# - GOOD DISTRIBUTION (writes spread evenly)
# - QUERY ISOLATION (most queries target one shard)
# - Monotonically-increasing keys (like timestamps or _id) -> hot shard problem
# Common patterns:
# - Hashed _id: spreads writes evenly; bad for range queries
# - Hashed customer_id: writes spread; queries per customer hit one shard
# - Compound (customer_id, created_at): range queries per customer use index
# Cannot change shard key after collection has data (until Mongo 6+; refinable since)
# ===== Chunks + balancer =====
# Data partitioned into CHUNKS (default 128 MiB).
# Balancer moves chunks between shards to maintain even distribution.
# Can be paused during sensitive maintenance.
# ===== Queries =====
# Targeted: shard key in the query -> mongos routes to one shard
# Broadcast: shard key NOT in query -> all shards queried, results merged
# Aim for targeted queries; design indexes + shard key for the hot patterns.
# ===== Trade-offs =====
# Pros:
# - Horizontal write scaling
# - Working set bigger than one node
# - Geographic data isolation
# Cons:
# - Operational complexity (multiple replica sets + routers + config)
# - Cross-shard transactions slower
# - Broadcast queries hit every shard
# - Shard key choice is hard to change
# ===== Atlas =====
# MongoDB Atlas manages sharding for you. Click 'enable sharding' on the cluster.
# Often the right answer instead of self-managing.
# ===== Patterns =====
# - Replica set first; shard only when you cannot scale up
# - Shard key chosen for both write distribution AND read locality
# - Indexes that match shard key + common queries
# - Monitor jumbo chunks + balancer activity
# ===== Pitfalls =====
# - Monotonic shard key -> all writes hit one shard
# - Low-cardinality shard key -> uneven distribution
# - Cross-shard joins / aggregations -> latency + cost
# - Trying to shard your way out of bad schema design
Why it matters
Sharding scales MongoDB horizontally: config servers + shards (each a replica set) + mongos routers. The shard key is the most important decision — high cardinality + good distribution + query isolation. Atlas hides most of this; self-managing is real ops work.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Distribute data across shards by a shard key.
sh.shardCollection('shop.orders', { customer_id: 1 });
Try it Yourself »
Discussion
Loading…