Skip to content
ExponaBLOG
MONGODB, NOSQL & DATA MODELING · DAY 053 / 100

Monitoring MongoDB: a MongoDB & NoSQL guide for developers

Watch the right metrics.

Expona Admin7 min read

Monitoring MongoDB: a MongoDB & NoSQL guide for developers means catching performance problems before they cascade into production incidents. You can't manage what you don't measure, and in distributed database systems, the right metrics separate smooth deployments from firefighting at 3 AM.

We've all experienced the moment when a seemingly small query starts timing out across your entire service layer. Without proper visibility into MongoDB's internals, you're flying blind. This guide walks through the metrics that matter, the tools that expose them, and the thresholds that should trigger your alerts.

Query latency and slow queries

Query latency is the frontline metric. It tells you whether your reads and writes are completing in reasonable time, and it surfaces application-level problems faster than almost anything else. When your median query time jumps from 5ms to 50ms, something has changed—either your data shape, your indexes, or your hardware load.

MongoDB's profiler is your primary weapon here. It logs queries that exceed a configurable threshold, letting you replay and analyze exactly what's slow. We typically enable it at the database or collection level rather than globally to avoid overwhelming log volume.

javascript
// Enable profiling for queries slower than 100ms
db.setProfilingLevel(1, { slowms: 100 })

// Query the profiler output
db.system.profile.find({
  millis: { $gt: 100 }
}).sort({ ts: -1 }).limit(10)

On production systems, we don't rely on the profiler alone—it carries overhead and storage cost. Instead, we ship query metrics to a centralized monitoring stack. MongoDB Atlas includes built-in slow query logging; self-hosted deployments benefit from tools like Percona PMM or custom instrumentation at the application driver level.

Look for patterns in slow queries: Do they hit large collections? Missing indexes? Involve $lookup or $group aggregations? A single slow query that runs rarely might be acceptable; one that runs hundreds of times per second demands optimization. Index creation and query rewrites often solve 80% of latency issues.

Connections and cursors

Connection exhaustion sneaks up on teams. Your application connection pool has a limit—typically 100-500 depending on your settings—and once you hit it, new requests queue or fail. Similarly, cursors that remain open consume memory and lock resources, especially problematic in long-running aggregations or tailable cursors for streaming data.

Monitor these server-side metrics via the serverStatus command:

javascript
// Get current connection and cursor state
db.adminCommand({ serverStatus: 1 }).connections
// Returns something like:
// { current: 245, available: 255, totalCreated: 5000 }

db.adminCommand({ serverStatus: 1 }).metrics.cursor
// Returns:
// { timedOut: 42, open: { total: 18, pinned: 2 } }

A growing number of open cursors signals that queries aren't finishing or clients aren't closing them properly. In a ride-hailing system we worked on, background workers were spawning aggregation cursors without cleanup, eventually saturating the server. The fix: explicit cursor closure in finally blocks or using framework patterns that handle it automatically.

On the application side, track connection pool utilization. If your pool regularly hits 95% capacity, increase it or investigate whether requests are holding connections longer than needed. Connection pools should be sized per-environment; a busy production API needs more than staging.

Replication lag

In any replicated MongoDB deployment—replica sets, sharded clusters—replication lag is critical to monitor. It measures how far behind secondary nodes are from the primary. When lag grows, secondaries serve stale data, and if the primary fails, failover takes longer or risks data loss.

Lag typically stays under a few milliseconds in healthy systems. We check it via the replication status:

javascript
// On any replica set member
rs.status()

// Look at this structure:
{
  set: "myReplicaSet",
  date: ISODate("..."),
  myState: 1,
  members: [
    {
      name: "mongo1:27017",
      self: true,
      health: 1,
      state: 1,
      stateStr: "PRIMARY"
    },
    {
      name: "mongo2:27017",
      health: 1,
      state: 2,
      stateStr: "SECONDARY",
      syncingTo: "mongo1:27017",
      optimeDate: ISODate("..."), // Lag is difference between primary's optime and this
      lastHeartbeat: ISODate("...")
    }
  ]
}

Replication lag spikes when:

  • The primary is under heavy write load and secondaries can't keep up
  • Network latency between nodes increases
  • Secondaries are performing large background operations (index builds, compaction)
  • Insufficient disk I/O bandwidth on secondaries

In a trading platform, we discovered that replication lag exceeded 5 seconds during market open when order volume spiked. The solution involved tuning the secondary's replicationOplogSizeMB, adding dedicated disk I/O for the oplog, and balancing read traffic across secondaries more carefully.

Set up alerts when lag exceeds your application's tolerance. If you perform reads from secondaries, lag directly impacts data freshness your users see.

Cache usage and disk I/O

MongoDB's WiredTiger storage engine uses memory as cache. When your working set fits in cache, reads serve from RAM at microsecond latencies. When it doesn't, MongoDB pages data from disk, and latency can spike 1000x. Monitoring cache hit ratio and disk I/O is essential for capacity planning.

Check cache behavior via serverStatus:

javascript
db.adminCommand({ serverStatus: 1 }).wiredTiger.cache
// Returns:
// {
//   bytes currently in the cache: 8589934592,
//   bytes read into cache: 123456789,
//   bytes written from cache: 987654321,
//   cache eviction value, in bytes: 234567890,
//   eviction worker thread created: ...,
//   % cached dirty: 15.2,
//   ...
// }

The key metric is cache eviction rate. If eviction is constant and high, your working set exceeds available cache. In an e-commerce system handling inventory, we found that peak traffic drove evictions to 20% per minute, causing tail latencies to stretch to 500ms. Adding more RAM resolved it, but we also partitioned data by region to reduce the working set per node.

Monitor disk I/O metrics from your infrastructure layer—IOPS, throughput, latency. SSDs should serve MongoDB; spinning disks lead to unpredictable performance. Watch for disk saturation; if your database is I/O-bound, you'll see high util% and queue depth in tools like iostat.

javascript
// Rough estimation of cache hit ratio (lower is worse)
const stats = db.adminCommand({ serverStatus: 1 })
const hitRatio = (stats.wiredTiger.cache['bytes read into cache'] - 
  stats.wiredTiger.cache['cache eviction value, in bytes']) / 
  (stats.wiredTiger.cache['bytes read into cache'] || 1)
console.log(`Cache hit ratio: ${(hitRatio * 100).toFixed(2)}%`)

Aim for cache hit ratios above 95% in steady state. Ratios dropping below 90% signal capacity stress and warrant investigation—either add memory, reduce working set, or distribute load across more nodes.

Common mistakes

  • Ignoring baseline metrics: You need to know what "normal" looks like before you can spot anomalies. Establish baselines for latency, connection count, and cache hit ratio during typical load, then alert when they deviate significantly.
  • Setting alerts too tight: If every minor fluctuation triggers a page, your team burns out and stops responding. Alerts should reflect real degradation, not natural variation. Use percentiles (p99 latency) rather than averages to catch tail behavior.
  • Profiling everything in production: MongoDB's profiler has overhead. Enable it selectively on problem collections or during investigation windows, not continuously on high-traffic systems.
  • Overlooking replication lag during upgrades: Upgrading a secondary takes it offline temporarily. During the window, lag is undefined, and if the primary fails, failover is risky. Plan upgrades carefully and monitor lag closely after each node restarts.
  • Not correlating metrics: High latency + high eviction rate + high disk I/O = classic capacity problem. High latency + normal cache + low I/O = likely an index issue. Connect the dots across multiple signals.

Key takeaways

  • Query latency and slow query logs reveal application-level problems first; enable the profiler selectively and ship metrics to centralized monitoring.
  • Track open connections and cursors to catch resource leaks; exhausted connection pools cause cascading failures.
  • Monitor replication lag on all secondaries; it directly impacts read freshness and failover safety.
  • Cache hit ratio and disk I/O indicate capacity health; eviction and saturation require immediate attention to maintain predictable latency.
  • Establish normal baselines before alerting; correlate multiple metrics to diagnose root cause rather than treating symptoms.
  • Use MongoDB Atlas built-in monitoring for managed deployments, or Percona PMM + custom instrumentation for self-hosted systems.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles