A replica set copies the same data to several servers, which protects it and can spread reads, but every member still holds all the data and the primary handles all the writes. When a collection grows to terabytes, or writes exceed what one primary can handle, adding a bigger server (vertical scaling) eventually stops being possible or affordable. Sharding scales horizontally: it splits a collection's data across several replica sets, called shards, so each holds and handles only part of it.
A sharded cluster has three parts. Shards store the data, each a replica set. mongos routers receive queries from applications and send each one to the right shards. Config servers store the metadata that says which ranges of data live where. To applications, the whole cluster looks like one database.
The most important decision is the shard key, the field or fields used to divide the data. A good key spreads data and writes evenly and lets common queries go to a single shard; a poor one creates hot spots and slow, cluster-wide queries. In this lesson you'll learn the architecture, choose shard keys with confidence, read sh.status(), and understand when sharding is the right move.
Cluster architecture
| Component | Role |
|---|---|
| Shard | A replica set holding a subset of the data |
| mongos | A router: applications connect to it, and it forwards each operation to the right shards |
| Config servers | A replica set storing the cluster's metadata: which chunk of data is on which shard |
| Chunk | A range of shard key values; the unit of data that moves between shards |
| Balancer | A background process that moves chunks to keep shards evenly loaded |
Applications use the same drivers and queries as before; they simply connect to the mongos routers instead of a replica set. Atlas creates and manages sharded clusters for you.
Choosing a shard key
A good shard key has:
- High cardinality: many distinct values, so data can be split into many chunks. A
countryfield with 20 values can't be spread across 50 shards. - Low frequency: no single value is extremely common, or one chunk becomes too big to split.
- Non-monotonic values for write-heavy data: a key that always increases, such as a timestamp or default ObjectId, sends every new insert to the same shard, creating a hot spot.
- Query isolation: most queries include the shard key, so mongos can target one shard instead of asking all of them.
Hashed sharding ({ customerId: 'hashed' }) spreads monotonic keys evenly, but range queries on the key must go to every shard. Ranged sharding keeps nearby values together, which helps range queries. Compound keys such as { tenantId: 1, orderDate: 1 } combine isolation with good distribution.
Targeted and scatter-gather queries
- A query that includes the shard key, such as
{ customerId: 'c42' }, is targeted: mongos sends it to one shard. - A query without the shard key, such as
{ status: 'pending' }, is scatter-gather: mongos sends it to every shard and merges the results, which costs more as the cluster grows. - Since MongoDB 5.0 you can reshard a collection to change its key, but it's a heavy operation, so choosing well first matters.
- Zone sharding pins ranges of data to particular shards, for example to keep European customers' data on servers in Europe.
MongoDB Operations Syntax
Sharding commands
sh.enableSharding('shop') // optional in MongoDB 6.0+
db.orders.createIndex({ customerId: 'hashed' })
sh.shardCollection('shop.orders', { customerId: 'hashed' })
sh.shardCollection('shop.events', { tenantId: 1, createdAt: 1 })
sh.status()
db.orders.getShardDistribution()
db.adminCommand({ reshardCollection: 'shop.orders', key: { region: 1, customerId: 1 } })
sh.addShardToZone('shard-eu', 'EU')MongoDB Operations Summary
- Sharding splits a collection across several replica sets (shards) to scale horizontally.
- mongos routers direct queries; config servers store which chunks live on which shard; the balancer evens them out.
- A good shard key has high cardinality, low frequency, avoids monotonic hot spots and appears in common queries.
- Hashed keys spread writes evenly; ranged keys suit range queries; compound keys can do both.
- Queries with the shard key are targeted; without it they scatter to every shard.
MongoDB Operations Examples
Each example shows the code, the output it produces and what each part does.
Sharding a collection
use shop
db.orders.createIndex({ customerId: 'hashed' })
sh.shardCollection('shop.orders', { customerId: 'hashed' }).ok
db.orders.getShardDistribution()switched to db shop
customerId_hashed
1
Shard shard-a at shard-a/a1:27018,a2:27018,a3:27018
{
data: '3.12GiB',
docs: 8105331,
chunks: 42,
'estimated data per chunk': '76.11MiB',
'estimated docs per chunk': 192984
}
---
Shard shard-b at shard-b/b1:27018,b2:27018,b3:27018
{
data: '3.09GiB',
docs: 8031472,
chunks: 41,
'estimated data per chunk': '77.17MiB',
'estimated docs per chunk': 195889
}
---
Totals
{
data: '6.21GiB',
docs: 16136803,
chunks: 83,
'Shard shard-a': [ '50.24 % data', '50.22 % docs in cluster', '403B avg obj size on shard' ],
'Shard shard-b': [ '49.75 % data', '49.77 % docs in cluster', '403B avg obj size on shard' ]
}Line-by-line explanation
- Line 2The shard key needs a supporting index; a hashed index suits customer ids.
- Line 3shardCollection splits the collection by the hash of customerId.
- Line 4getShardDistribution shows how data is spread: here almost exactly half on each shard. The sizes are from a production-sized cluster.
Targeted versus scatter-gather queries
const e1 = db.orders.find({ customerId: 'c42' }).explain()
e1.queryPlanner.winningPlan.stage
e1.queryPlanner.winningPlan.shards.length
const e2 = db.orders.find({ status: 'pending' }).explain()
e2.queryPlanner.winningPlan.stage
e2.queryPlanner.winningPlan.shards.lengthSINGLE_SHARD
1
SHARD_MERGE
2Line-by-line explanation
- Lines 1 to 3The query includes the shard key, so mongos sends it to just one shard.
- Lines 5 to 7Without the shard key, every shard must be asked and the results merged.
- Line 7With two shards the cost is modest; with fifty, scatter-gather queries become expensive.
Why a timestamp makes a poor shard key
// ranged shard key on an always-increasing field
sh.shardCollection('logs.events', { createdAt: 1 }).ok
// after a busy hour of inserts: documents per shard
db.getSiblingDB('logs').events.aggregate([{ $collStats: { storageStats: {} } }, { $project: { _id: 0, shard: 1, count: '$storageStats.count' } }])1
[ { shard: 'shard-a', count: 0 }, { shard: 'shard-b', count: 5000000 } ]Line-by-line explanation
- Line 2Every new event has a later createdAt than the last, so all inserts land in the last chunk.
- Line 4That chunk lives on one shard, which takes every write: a hot spot. The balancer moves older data later, but new writes keep landing on one shard. A hashed key, or a compound key starting with something like deviceId, spreads the writes instead.
Common MongoDB Operations Mistakes
A low-cardinality shard key
sh.shardCollection('shop.users', { country: 1 }) // a few values: chunks can't be split, shards fill unevenlysh.shardCollection('shop.users', { _id: 'hashed' })Queries that never include the shard key
// sharded on customerId, but the busiest page queries by email
db.users.find({ email: e }) // scatter-gather on every login// choose a shard key used by the hottest queries, or keep a lookup collection from email to customerIdSharding to fix a missing index
// queries are slow, so the team adds three shardsdb.orders.find(q).explain('executionStats') // fix the index or query firstMongoDB Operations in Real Projects
Sharding in practice
Large SaaS products shard by tenant or account id so each customer's data stays together and queries are targeted. IoT platforms use compound keys like device id plus time to spread writes. Global apps use zone sharding to keep data in the right region for latency and data-protection rules. Many companies never need to shard at all: a well-tuned replica set handles a remarkable amount of data and traffic.
MongoDB Operations FAQ
When should I shard a MongoDB collection?
Shard when one replica set genuinely can't keep up: the data no longer fits comfortably on one server, write throughput exceeds what one primary can handle, or rules require data to live in particular regions. Before that, fix indexes, queries and schema, archive old data and scale up the servers. Sharding is powerful but adds lasting complexity.
Can I change the shard key in MongoDB?
Yes, in modern versions. MongoDB 4.4 added refineCollectionShardKey, which adds extra fields to the end of an existing key, and MongoDB 5.0 added reshardCollection, which changes the key completely by rewriting the collection's data. Resharding is resource-intensive and needs spare disk space, so choosing a good key at the start is still important.
What is a jumbo chunk in MongoDB?
A jumbo chunk is a chunk that has grown beyond the maximum chunk size but can't be split, usually because many documents share the same shard key value. The balancer can't move it easily, so one shard ends up holding more than its share. The cure is a shard key with higher cardinality, for example a compound key that adds a more varied field.
What is the difference between hashed and ranged sharding?
Ranged sharding stores documents with nearby shard key values in the same chunk, which makes range queries on the key efficient but can create hot spots for increasing keys like timestamps. Hashed sharding distributes documents by a hash of the key, spreading inserts evenly, but range queries on that key have to ask every shard. Choose based on whether your workload is dominated by range queries or by heavy inserts.
Does my application code change when I shard MongoDB?
Very little. Applications connect to the mongos routers instead of a replica set and use the same drivers, queries and updates. The main differences are performance, since queries that include the shard key are targeted while others go to every shard, and some rules for operations such as updateOne and unique indexes, which interact with the shard key.
MongoDB Operations Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the command that shards the orders collection on a hashed customerId.
sh.('shop.orders', { customerId: 'hashed' })
What does sharding do?
Which component routes application queries to the right shards?
Why is an always-increasing value a poor ranged shard key?
What's a scatter-gather query?
MongoDB Operations Quiz
5 questions to check what you learned.
What is each shard in a production cluster?
- A single server
- A collection
- A mongos router
- A replica set
What does the balancer do?
- Balances CPU usage
- Moves chunks between shards to keep data evenly distributed
- Elects primaries
- Balances read preferences
What does high cardinality mean for a shard key?
- Many distinct values, so data can be split into many chunks
- Few distinct values
- Large values
- Values that change often
What should you try before sharding?
- Nothing, shard early
- Deleting indexes
- Turning off replication
- Better indexes and queries, archiving old data and a well-sized replica set
What is zone sharding used for?
- Time zones
- Keeping ranges of data on particular shards, such as EU data on EU servers
- Hashing keys
- Backups