Scaling MongoDB horizontally with sharding: understanding when a dataset needs to be split, the sharded cluster architecture consisting of shards, config servers, and mongos, and choosing the right shard key between ranged and hashed sharding.

The replica set in episode 15 guarantees high availability and read scaling. But there's a limit that can't be broken: storage and write throughput are still limited by one primary. If a dataset reaches terabytes and writes reach hundreds of thousands per second, no matter how big a server you buy — one physical server will be overwhelmed. The answer is sharding: splitting data across many servers horizontally.
Episode 16 teaches you the horizontal-scale mindset. The roadmap: first we determine when sharding is truly needed, second we dissect the sharded cluster architecture — shards, config servers, and mongos, third we understand the shard key, and fourth we compare ranged versus hashed sharding. Let's get started.
Sharding adds infrastructure complexity — so don't use it before it's genuinely needed. Two clear signals that the time has come:
Beyond that, there are supporting indicators: the working set (data accessed often) starts exceeding the server's RAM, and queries keep getting slower even when well indexed. If those signals haven't appeared yet, a scaled-up replica set is simpler and cheaper — sharding is a big architectural decision, not a minor tuning.
A sharded cluster has three components with very different roles:
| Component | Role |
|---|---|
| Shard | Each shard is a replica set storing a data subset. Adding a shard adds storage and write capacity. |
| Config Servers | A dedicated replica set storing metadata and routing — information about which shard holds a piece of data. |
| mongos | The query router. Accepts queries from the application, consults the config servers, then routes queries to the right shards and combines the results. |
App ---> mongos ---> config servers (metadata)
|
+--> shard A (data subset)
+--> shard B (data subset)
+--> shard C (data subset)The key point: applications never talk directly to shards. The application only communicates with mongos — which looks like a regular mongod — and mongos handles the rest. This keeps the application experience simple even though there are dozens of servers behind the scenes.
Data in a sharded collection is split into chunks — continuous data ranges based on the shard key. These chunks are distributed across the shards. When one shard is overloaded and another is idle, the balancer (a background process) moves chunks to even out the load automatically. This is what lets a sharded cluster "heal" its own data distribution.
The shard key is the field (or field combination) that determines how documents are distributed across shards. MongoDB divides the shard key value ranges into chunks, and places each chunk on one shard. Choosing the shard key is the most important and most difficult-to-change decision in a sharded cluster — choose it before the collection grows, because changing the shard key after data is distributed is extremely complex.
A good shard key has three qualities:
true/false), data only spreads across two shards — the rest stay idle.createdAt or auto-increment will always route new writes to one last shard — concentrating the load and defeating distribution.An example of a good shard key: the combination { customerId: 1, orderDate: 1 } in an orders collection — customerId has many unique values, none dominates, and time distribution is spread out.
Ranged sharding splits data based on shard key value ranges. Queries filtering a certain value range can be routed precisely to the shard holding that range — very efficient for range queries and operations grouping nearby values.
sh.enableSharding("app")
sh.shardCollection("app.orders", { customerId: 1 })Its main weakness: if the shard key rises monotonically, all new writes pile onto one shard (a hot spot). Ranged sharding works best when the shard key is naturally evenly distributed.
Hashed sharding computes a hash of the shard key value then distributes it evenly across chunks. The hash ensures sequential values spread to different chunks — drastically eliminating the hot spot problem, even for monotonically rising shard keys.
sh.enableSharding("app")
sh.shardCollection("app.events", { deviceId: "hashed" })The consequence: range queries are not efficient — because sequential values are scattered randomly, a range query has to reach many shards. Hashed sharding is ideal for write-heavy workloads and point-lookup queries (based on a single value), like event logs accessed per device.
To understand how a sharded cluster works, there's no better teacher than hands-on practice. Imagine we build a minimal cluster: one mongos, one config server, and two shards. First, start the config server as a single-member replica set:
mongod --configsvr --replSet cfgrs --dbpath /data/configdb --port 27019The config server must be run with the --configsvr flag and as a replica set. After that, start two shards — each a simple single-member replica set:
mongod --shardsvr --replSet rs1 --dbpath /data/shard1 --port 27017
mongod --shardsvr --replSet rs2 --dbpath /data/shard2 --port 27018Finally, start mongos as the application entry point:
mongos --configdb cfgrs/localhost:27019 --port 27017Then register both shards to the cluster via mongos:
mongosh "mongodb://localhost:27017"
sh.addShard("rs1/localhost:27017")
sh.addShard("rs2/localhost:27018")
sh.status()sh.status() displays the cluster's complete map: registered shards, sharded databases, and chunk distribution. This is the verification point that your cluster is healthy before traffic comes in.
Warning
Once a collection is sharded, the shard key can't be changed. If the shard key design is wrong — the classic example is choosing monotonically increasing createdAt — you'll be stuck with hot shards forever or need a massive data migration. Spend time analyzing access patterns before choosing. The only reasonable way out is rebuilding the collection from scratch in a new cluster.
Info
The rule of thumb: hashed sharding for mass-write workloads and point lookups (events, logs, sessions); ranged sharding for workloads using range queries per natural group (orders per customer within a time range). When in doubt on a write-heavy collection with a monotonically rising shard key, hashed is almost always the safe choice.
In episode 16 you understood sharding as the path to horizontal scale: splitting terabyte datasets and write throughput beyond one replica set's capacity. You got to know the sharded cluster architecture — shards storing data subsets, config servers storing routing metadata, and mongos as the query router — along with the chunk and balancer mechanism that evens out load automatically. Finally, you mastered choosing an ideal shard key (high cardinality, low frequency, non-monotonic) and the difference between ranged and hashed sharding.
Key takeaways:
In the next episode, episode 17, we secure everything: Security: Authentication, Authorization & Encryption. You'll enable SCRAM authentication, build RBAC with built-in roles and custom roles, then understand encryption at rest, TLS for encryption in transit, and client-side field level encryption for sensitive fields. See you in episode 17!