Chris Collins

Tools · infra

MongoDB replica sets and sharding, simulated

An animated MongoDB cluster in your browser: a replica set with its oplogs, elections in terms, write concern and the rollback of acknowledged w:1 writes, read concern and read preference with maxStalenessSeconds; a sharded cluster with mongos, config servers, ranges, hashed and ranged keys, zones, the balancer and jumbo ranges; a query-targeting checker and a shard-key evaluator.

Added

Works with

How to use it

A MongoDB deployment in miniature that runs entirely in this page: a replica set — the members, each with its oplog, and a client driver — and a sharded cluster — the application, mongos, the config servers and the shards with the ranges of the shard key they own. Every write, oplog batch, heartbeat, vote, read, query and range migration is drawn as it happens, and the rules — when a write is acknowledged, who may become primary, what a read can see, where a query goes, when the balancer moves data — follow the MongoDB manual for 6.0 and later. Nothing here talks to a real MongoDB; for a console on a single (emulated) node, see the MongoDB playground.

How to use it

The Replica set and Sharded cluster tabs are simulators. Pick a scenario and press Start. Each step does something — writes, reads, kills a member, cuts the network, inserts, queries — then plays until it has happened and pauses so you can read what happened and why, with links to the manual. Next step moves on, Back rewinds (the simulator is deterministic, so it replays the earlier steps), ⏭ jumps to the end of the step and Step ⇥ advances to the next single event. Space plays and pauses; → is the next step. Each tab has a playground with no script. Speed scales everything; Hop time is how long a labelled message takes to cross a wire at 1× — while one is on its way the simulated clock slows down — and Sim clock turns that off. ⛶ Full screen (or F) gives the tool the whole window.

Replica set. The client (a driver) at the top and one card per member: its state (PRIMARY, SECONDARY, ARBITER, ROLLBACK, DOWN) and term, its priority and flags (hidden, delayed, slow, stalled), the election timer as a ring, and its oplog — one cell per entry, coloured by the term it was written in, labelled with the key it set (· for a no-op). A faded cell has been fetched but not yet applied; a dashed amber outline is not yet in the journal; a red outline differs from the primary’s entry at that position; the black bar underneath is the majority commit point. Below the oplog: applied and committed positions, the replication lag, and the member’s data as a local read and as a majority read would see it. Heartbeats are drawn as small dots; writes, oplog batches, positions, votes and reads as labelled packets. Tap a member to kill or restart it, cut it off, slow or stall it, step it down or make it stand for election; tap the client to write and read. Do something writes with any write concern (w, j, wtimeout) and reads with any read concern, read preference and maxStalenessSeconds. Panels: Members (like rs.status()), Client requests (every write and read with its result — ROLLED BACK and STALE are flagged) and Server selection (the driver’s view of the members, each secondary’s estimated staleness and which are eligible for the current read preference).

Sharded cluster. The application, mongos with the version of its cached routing table, the config servers with the real version and the balancer’s state, and one card per shard: its documents, the inserts it took in the last five seconds (🔥 when it is the only one taking any) and its ranges as blocks (width by documents; amber outline = just inserted into; hatched = jumbo; dashed = moving). Underneath, the whole routing table as a strip in key order, from MinKey to MaxKey. Do something inserts one document or twenty, starts steady traffic, runs a find you type (or pick) and stops or starts the balancer. Panels: Last query (targeted or scatter-gather, which shards, why, the explain stage) and Routing table (config.chunks).

Query targeting. Type a filter as you would in mongosh — { customerId: 42, createdAt: { $gte: ISODate("2026-03-01") } } — and a shard key — { customerId: 1, createdAt: 1 } or { _id: "hashed" }. The tool splits 3 000 sample orders into ranges over the shards and shows whether mongos can target the query, which ranges and shards it reads, the bounds it computes on the shard key, the explain stage and the rule behind it.

Shard key evaluator. Pick or type a candidate key. It reports what analyzeShardKey reports in 7.0 and later — cardinality, the most common values and their share, monotonicity as the correlation between key order and insert order — and what the key would do: how many ranges and jumbo ranges, documents per shard, where the next 300 inserts land, which of a typical workload’s queries are targeted, and a verdict, with a table comparing ten candidate keys.

Scenarios

Replica set:

  1. Writes, the oplog and write concern — w:1 answered at once, secondaries pulling the oplog, w:"majority" and the commit point, a slow secondary and replication lag, w:3 with wtimeout and why a write-concern error does not undo the write.

  2. Failover: an election — heartbeats, the primary dies mid-write, a dry-run election then the real one in term 2, the driver’s retryable write, the old primary rejoining.

  3. Rollback: acknowledged, then lost — the primary cut off with the client keeps acknowledging w:1 writes, the majority elects a new primary, the old one steps down and, when the network heals, rolls the acknowledged writes back; why w:"majority" prevents it.

  4. Read concern and stale reads — local on a stalled secondary, local and majority on the primary right after a w:1 write, linearizable and its no-op, snapshot.

  5. Read preference and maxStalenessSeconds — the 90-second minimum, a secondary falling minutes behind, the driver’s staleness estimate leaving it out, nearest.

  6. Priorities and priority takeover — a priority-2 member fails, returns, catches up and takes the primary role back.

  7. An arbiter: primary–secondary–arbiter — elections still work with a data member down, but w:"majority" cannot be acknowledged.

  8. Hidden and delayed members — a member that applies the oplog 30 s late, and a mistake it still does not have.

  9. Replica set playground.

Sharded cluster:

  1. Routing through mongos — the components, an insert routed by its hashed key, a targeted query, a scatter-gather query, and why a hashed key cannot target a range.

  2. An increasing shard key: one hot shard — every insert to the range ending at MaxKey; the balancer moves cold ranges but the inserts never spread.

  3. The balancer and stale routing — a collection on its primary shard, a migration (clone, catch-up, commit, version bump), mongos answered with StaleConfig, refreshing and retrying.

  4. A low-cardinality key: jumbo ranges — sharded on a three-valued field, each value one unsplittable range, marked jumbo and never moved.

  5. Zones: data where it belongs — a zone per region pinned to a shard, inserts landing in their zone, a targeted query for one region.

  6. Sharded cluster playground.

What it models

  • Replication. The primary applies a write, appends it to its oplog with an optime (term, position) and its wall-clock time, and journals it (at once with j: true, otherwise at the next group commit, 100 ms). Each secondary keeps a getMore open on its sync source’s oplog (a tailable, awaiting cursor), applies the batches it receives and reports its applied and journaled positions back (replica set data synchronisation). The primary writes a no-op every 10 s when idle, as periodicNoopIntervalSecs does, so that staleness can be measured.

  • Write concern (manual). w: 0 is not acknowledged; w: 1 when the primary has applied it (and journaled it with j: true); w: n when n data-bearing members have applied it; w: "majority" when a majority of voting data-bearing members have journaled it — the count is the smaller of a majority of all voting members and the number of voting data-bearing members, so an arbiter votes but never acknowledges. wtimeout returns an error but leaves the write in place. A primary that steps down answers its waiting writes with an error; retryable writes (on by default) retry once on the new primary.

  • The commit point. The highest oplog entry of the primary’s own term that a write-majority has journaled; everything up to it is majority-committed and can never be rolled back. Members learn it from oplog batches and heartbeats.

  • Elections (protocol version 1; replica set elections). Heartbeats every 2 s. A secondary that is electable (data-bearing, priority above 0, not hidden or delayed) starts an election when it has not heard from a primary for electionTimeoutMillis (10 s) plus a random offset of up to 15 %. It first runs a dry run (asking whether voters would vote for it in the next term, without incrementing its own), then increments its term, votes for itself and asks for votes. A voter refuses a candidate whose term is older than its own, one it when it has already voted for another candidate in that term, or one whose last applied optime is older than its own. A majority of votes makes it primary; it catches up from any member it can see that is further ahead, then writes a no-op in the new term and accepts writes. A primary steps down when it sees a higher term or cannot see a majority of voting members for an election timeout. A caught-up secondary with a higher priority than the primary calls a priority takeover election.

  • Rollback (rollbacks during failover). A member whose oplog diverges from its sync source’s finds the last common entry, undoes everything after it (saving the documents to a rollback file) and fetches from there. Writes acknowledged with w:1 that the majority never had are counted as acked but lost. A crash loses what was applied but not yet journaled.

  • Read concern. local (and available) reads the member’s latest applied data; majority and snapshot read the member’s majority-committed data; linearizable runs only on the primary, which writes a no-op and waits for a majority to acknowledge it before answering (read concern).

  • Read preference and staleness. The driver checks every member it can see every 10 s (heartbeatFrequencyMS; hidden members and arbiters are never in its list). Server selection follows the drivers' Server Selection specification: primary, primaryPreferred, secondary, secondaryPreferred, nearest; with maxStalenessSeconds each secondary’s staleness is estimated as (S.lastUpdateTime − S.lastWriteDate) − (P.lastUpdateTime − P.lastWriteDate) + heartbeatFrequencyMS (or from the freshest secondary when there is no primary), and values below 90 s or below heartbeatFrequencyMS + idleWritePeriodMS are refused (Max Staleness specification). Among eligible members, those within localThresholdMS (15 ms) of the fastest round trip are chosen from at random.

  • Sharding (manual). Documents belong to ranges [min, max) of the shard key, compared in BSON order (MinKey, numbers, strings, ObjectIds, dates, MaxKey); compound keys compare field by field; a hashed field is replaced by its hash. A new collection with a ranged key is one range on the primary shard; with a hashed key it is pre-split over every shard (two ranges each here). mongos routes with a cached copy of the routing table; a shard that sees an older shard version answers StaleConfig and mongos refreshes from the config servers and retries. Zones split ranges at their boundaries and keep them on their shards.

  • The balancer (sharded cluster balancer), as in 6.1 and later: ranges are not split on insert; each round, a range in the wrong zone moves first, then if the fullest and emptiest shards differ by at least three times the range size, a range of about the range size is split off the fullest shard and moved to the emptiest — clone, catch-up, commit on the config servers (the collection’s major version goes up), then the donor deletes its copy in the background. A range above the range size whose documents all share one key value cannot be split, is marked jumbo and is never moved.

  • Query targeting (query routing). The filter’s bounds on the shard key: equality or $in on a prefix narrows to points, the first range ends the narrowing (later fields are MinKey…MaxKey), a filter without the first field is sent to every shard, a hashed field is narrowed only by equality, $or is targeted clause by clause. Range operators bracket by type, as MongoDB’s do. The shards whose ranges overlap the bounds are asked; explain on mongos shows SINGLE_SHARD or SHARD_MERGE.

  • The shard-key evaluator (choose a shard key, analyzeShardKey). Cardinality is the number of distinct key values; frequency the share of the most common ones; monotonicity the correlation between the order of documents by key and by insertion, called monotonic at |r| ≥ 0.7. The dataset is split into ranges of the chosen size (never between equal keys) over the shards, the next 300 generated orders are placed to see where inserts go, and five typical queries are checked for targeting.

Limits

  • Real timings (heartbeats, election timeout, the driver’s 10 s checks) but played faster; the network latency is fixed and small. A few members, three keys (x, y, z) and a handful of values; documents are not stored in the replica set, only the oplog that sets them.

  • Not modelled in the replica set: initial sync, chained replication (every secondary syncs from the primary), votes: 0 members, reconfiguration, catch-up takeover, read concern available’s difference on sharded clusters, `afterClusterTime and causal consistency, transactions, the oplog’s size and window, flow control, and the WiredTiger cache pressure in a PSA set (described, not simulated). snapshot is shown as the member’s majority-committed state.

  • In the sharded cluster each shard is one box, not a replica set; there is one mongos and one config server box. Range size is counted in documents (standing in for 128 MB). Not modelled: auto-merging, moveChunk throttling and _waitForDelete, orphaned documents, resharding, refineCollectionShardKey (described), sharded transactions, aggregation pipelines across shards, sorts (SHARD_MERGE_SORT) and updates or deletes without the shard key.

  • The hash is a 32-bit stand-in for MongoDB’s 64-bit hash of the value (an MD5-based hash), so the ranges a hashed value falls into are not the ones a real cluster would use; the spread is the same.

  • The evaluator’s thresholds (when cardinality is "low", a value "hot", inserts "concentrated") are this tool’s judgment, not MongoDB’s.

Linking to an example

Links can be written by hand. Add a tab after #: replset (the default), sharded, query or evaluator; a sharded-cluster example or a query or evaluator parameter opens its own tab. A link’s settings replace this page’s saved settings (a button restores yours).

Parameter Meaning Example

example

A scenario from either list below, with its own settings; parameters given with it override them

example=rollback

scenario

The replica-set scenario, without its settings

scenario=election

step

Open the replica-set scenario at this step

step=2

shscenario

The sharded-cluster scenario (with #sharded)

shscenario=sh-zones#sharded

shstep

Open the sharded-cluster scenario at this step

shstep=1

members

Data-bearing members, 1–7

members=5

arbiter

Add an arbiter (true/false)

arbiter=true

hidden

Add a hidden member

hidden=true

delay

Add a delayed member with this secondaryDelaySecs

delay=60

priorities

Priorities of M1, M2, …

priorities=2,1,1

w

Default write concern: majority, 0–7

w=1

j

j: true

j=false

wtimeout

Default wtimeout, ms

wtimeout=2000

rc

Default read concern: local, majority, linearizable, snapshot

rc=majority

rp

Default read preference: primary, primaryPreferred, secondary, secondaryPreferred, nearest

rp=nearest

maxStaleness

Default maxStalenessSeconds (-1 none)

maxStaleness=90

electionTimeout

electionTimeoutMillis

electionTimeout=5000

latency

One-way network latency between members, ms

latency=20

shards

Shards in the sharded cluster, 2–6

shards=4

key

Shard key: customerId, orderId, region or region+customerId

key=orderId

hashed

Hash the key’s last field

hashed=true

zones

A zone per region (uses region+customerId)

zones=true

rangeDocs

Range size in documents

rangeDocs=40

docs

Documents in the collection at the start

docs=200

balancer

Balancer on

balancer=false

q

Query targeting: the filter

q={ status: "pending" }

sk

Query targeting: the shard key

sk={ customerId: "hashed" }

qshards

Query targeting: shards

qshards=6

ek

Evaluator: the candidate key

ek={ region: 1, _id: 1 }

eshards, erange, edocs

Evaluator: shards, range size, documents

eshards=8

seed

Random seed

seed=7

speed

Playback speed: 0.25, 0.5, 1, 2, 4 or 8

speed=2

hop

Hop time in seconds (0.25, 0.5, 1, 2, or 0.1–5) or clock

hop=1

Replica-set scenarios:

example= Shows

replication

Writes, the oplog, w:1, w:"majority", replication lag, wtimeout (open)

election

Failover: dry run, vote, new term, retryable write (open)

rollback

Acknowledged w:1 writes rolled back after a partition (open)

read-concern

local, majority, linearizable and snapshot reads; stale reads from a secondary (open)

staleness

maxStalenessSeconds: the 90 s minimum and a lagging secondary left out (open)

priority

Priorities and priority takeover (open)

arbiter

A PSA set: elections with a member down, w:"majority" blocked (open)

delayed

Hidden and delayed members (open)

rs-playground

A three-member replica set to experiment with (open)

Sharded-cluster scenarios:

example= Shows

sh-basics

mongos, config servers, shards; targeted and scatter-gather queries (open)

sh-monotonic

An increasing key sends every insert to one shard (open)

sh-balancer

Range migration and mongos’s stale routing table (open)

sh-jumbo

A three-valued key and its jumbo ranges (open)

sh-zones

Zones by region (open)

sh-playground

A sharded collection to experiment with (open)

Sources: the MongoDB manual — Replication, Replica Set Elections, Replica Set Oplog, Write Concern, Read Concern, Read Preference, maxStalenessSeconds, Rollbacks During Replica Set Failover, Replica Set Arbiter, Delayed Members, Retryable Writes, Sharding, Hashed Sharding, Zones, Sharded Cluster Balancer, Choose a Shard Key, analyzeShardKey and BSON comparison order; the MongoDB drivers' Server Selection and Max Staleness specifications; and the server’s replication internals README (protocol version 1, dry-run elections, catch-up, priority takeover).

Runs entirely in your browser; nothing you type leaves this page.