Running & observing a deployment

This section documents the current MongoDB 8.x server line as published at the MongoDB Server Manual, which is the reference these pages are written and verified against. No specific patch version is pinned. Some capabilities (Atlas Search, Atlas Vector Search, and parts of encryption and backup) are Atlas-only — they are linked, not documented in depth.

This content was generated with the assistance of AI and should be verified against the official manual before being relied on in production, since MongoDB iterates quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

Operating a MongoDB deployment comes down to three things: bringing mongod up and down cleanly, watching what it is doing right now, and tracking the handful of metrics that predict trouble before it happens. This page covers each in turn, plus the host-level settings the manual expects a production server to have.

Starting and stopping mongod

mongod takes its settings either as command-line flags or from a YAML configuration file passed with --config (or -f). The file is the better choice for anything permanent: it is version-controllable, self-documenting, and identical across restarts. Flags are handy for one-off overrides and for containerised setups.

The configuration file groups options into a small number of top-level sections — storage, net, replication, sharding, security, and systemLog are the ones seen on almost every deployment.

# /etc/mongod.conf
storage:
  dbPath: /var/lib/mongo
  wiredTiger:
    engineConfig:
      cacheSizeGB: 8

systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true

net:
  port: 27017
  bindIp: 127.0.0.1,10.0.0.11
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongod.pem

security:
  authorization: enabled
  keyFile: /etc/ssl/mongo-keyfile

replication:
  replSetName: rs0

# On a shard member, identify its cluster role:
sharding:
  clusterRole: shardsvr
# Start with the config file.
mongod --config /etc/mongod.conf

# Override a single option at launch (flags win over the file).
mongod --config /etc/mongod.conf --port 27018

# Under systemd on most Linux packages:
sudo systemctl start mongod

Every key in the file has a documented equivalent flag; see Configuration File Options for the full list and the flag-to-key mapping.

Clean shutdown

Always stop mongod in a way that lets it flush its journal and close storage files. Any of the following is clean: db.shutdownServer() from mongosh against the admin database, SIGTERM to the process (what systemctl stop mongod sends), or mongod --shutdown. Avoid SIGKILL — the next start then has to run journal recovery. On a replica-set primary, step down first (rs.stepDown()) so a secondary takes over with minimal write interruption.

// From mongosh, connected to the node you want to stop:
use admin
db.shutdownServer()          // refuses if it would lose un-replicated writes
db.shutdownServer({ force: true, timeoutSecs: 60 })

See Manage mongod Processes and Storage & durability for what the journal guarantees across a crash.

Seeing what the server is doing

currentOp and killOp

db.currentOp() lists in-progress operations — their opid, how long they have been running, the namespace, the query shape, and what they are waiting on. db.killOp(opid) asks the server to abort one. This is the first tool to reach for when the deployment is slow now.

// Operations running longer than 3 seconds, excluding idle connections.
db.currentOp({
  active: true,
  secs_running: { $gte: 3 },
  "command.collection": { $exists: true }
})

// Stop a runaway operation by its opid.
db.killOp(184230)

The database profiler

The profiler writes a document to the capped system.profile collection in each database for operations you tell it to capture. It has three levels:

  • 0 — off (the default).

  • 1 — capture only operations slower than slowms (default 100 ms).

  • 2 — capture every operation (expensive; use briefly).

// Capture operations slower than 50 ms in the current database.
db.setProfilingLevel(1, { slowms: 50 })

db.getProfilingStatus()      // { was: 1, slowms: 50, sampleRate: 1 }

// The 5 slowest recently profiled operations.
db.system.profile.find().sort({ millis: -1 }).limit(5).pretty()

db.setProfilingLevel(0)      // turn it back off

Even with the profiler off, operations exceeding slowms are logged to systemLog. See Manage the Database Profiler and Database Profiler Output reference.

explain for one query

When the profiler or the log points at a specific query, run it through explain to see whether it used an index, how many documents it examined versus returned, and the winning plan. "executionStats" actually runs the query and reports real counts.

db.orders.find({ customerId: 42, status: "OPEN" })
         .sort({ orderDate: -1 })
         .explain("executionStats")
// Watch: totalKeysExamined vs totalDocsExamined vs nReturned, and stage = IXSCAN not COLLSCAN.

See cursor.explain() and Indexes for reading the plan output and fixing what it reveals.

Monitoring

Server-level counters: serverStatus

db.serverStatus() is a large one-shot snapshot of counters and gauges: connections, opcounters, the WiredTiger cache, the replication position, lock and queue state, network bytes, and memory. Sample it on an interval and graph the deltas rather than reading it once.

const s = db.serverStatus();
({
  connections:  s.connections,                         // current / available
  cacheUsedMB:  s.wiredTiger.cache["bytes currently in the cache"] / 1024 / 1024,
  cacheMaxMB:   s.wiredTiger.cache["maximum bytes configured"] / 1024 / 1024,
  queues:       s.globalLock.currentQueue,             // readers / writers waiting
  opcounters:   s.opcounters
})

Data size: dbStats and collStats

db.stats() reports storage and index sizes for a whole database; db.<coll>.stats() does the same per collection, plus per-index sizes and, for a sharded collection, the per-shard distribution.

db.stats(1024 * 1024)                        // sizes in MB
db.orders.stats()                            // storageSize, totalIndexSize, indexSizes, sharding

See dbStats and collStats.

Live streams: mongostat and mongotop

mongostat prints one line per interval with cluster-wide rates — inserts, queries, updates, deletes, getmores, flushes, resident/virtual memory, network in/out, and connections. mongotop breaks read and write time down by collection, which pinpoints which collection is hot.

mongostat --uri "mongodb://localhost:27017" 2      # refresh every 2 seconds
mongotop  --uri "mongodb://localhost:27017" 5      # per-collection read/write ms, every 5 seconds

See mongostat and mongotop.

Hosted metrics

Atlas and Cloud Manager collect the same counters continuously, retain history, and drive alerts without you running anything on the host. They are the managed alternative to a self-hosted metrics pipeline; this page documents the self-hosted tools, and the hosted dashboards are covered at Atlas Monitoring and Alerts.

What to watch

  • Page faults / disk I/O — a rising rate means the working set no longer fits in RAM.

  • Replication lag — rs.printSecondaryReplicationInfo() or the repl lag metric; a secondary falling behind threatens w: "majority" latency and failover safety. See Replication.

  • Connections — approaching the configured limit causes new clients to be refused; usually a driver pool misconfiguration.

  • WiredTiger cache pressure — cache used near the maximum, plus eviction threads running, means reads and writes start stalling on eviction.

  • Queue depth — non-zero globalLock.currentQueue readers or writers means operations are waiting on locks or tickets.

See Monitoring for MongoDB for the full metric catalogue and suggested thresholds.

Production notes (host tuning)

The manual expects a production Linux host to be configured as follows before it carries real load:

  • Filesystem — use XFS for the dbPath volume with WiredTiger; it handles MongoDB’s allocation and fsync patterns better than ext4.

  • Transparent Huge Pages — disable THP (and defrag); THP hurts MongoDB’s memory-access pattern and causes latency spikes.

  • NUMA — start mongod with an interleave policy (numactl --interleave=all) or disable NUMA in the BIOS, so memory is not starved on one node.

  • ulimit — raise open-files and process/thread limits well above the defaults (the packages ship a recommended LimitNOFILE/LimitNPROC); the manual gives target values.

  • Readahead — set a low block-device readahead (around 8—​32 KB); large readahead wastes cache on data MongoDB did not ask for.

  • Clock sync — run NTP (or chrony) on every host; replica-set and sharded-cluster logic depends on loosely synchronised clocks.

  • Dedicated disks — put the data volume on its own physical devices, separate from the OS and logs.

# Start mongod with NUMA interleaving.
numactl --interleave=all mongod --config /etc/mongod.conf

# Confirm THP is disabled.
cat /sys/kernel/mm/transparent_hugepage/enabled     # want: [never]

See Production Notes for the exact values and the rationale behind each, and Administration for the wider set of operational tasks.