MongoDB’s WiredTiger storage engine maintains its own internal cache independent of the OS page cache, and when that cache fills beyond capacity, eviction pressure causes reads to go to disk — a transition that happens silently until IOPS spike and ops/sec drops. The default cache size is 50% of available RAM minus 1 GB, but the uncompressed nature of the cache means a dataset that looks modest on disk can consume several times more memory once loaded into WiredTiger.

Situation

WiredTiger has been MongoDB’s default storage engine since version 3.2. It stores data compressed on disk but decompresses pages into the internal cache when they are loaded for reads or writes. A collection that occupies 10 GB on disk with snappy compression might occupy 25–35 GB in the WiredTiger cache, because the cache holds the uncompressed representation.

Engineers managing MongoDB capacity frequently size hardware based on disk footprint or compressed data size. That works until the working set exceeds the uncompressed cache size, at which point WiredTiger begins evicting pages to make room for new reads — and those evicted pages, when needed again, require disk reads.

The OS page cache sits below WiredTiger and caches the compressed on-disk representation. MongoDB uses both layers, but WiredTiger’s internal cache governs how much uncompressed working set fits in memory. The distinction matters when diagnosing whether a performance problem is a WiredTiger cache miss or an OS-level page cache miss.

The Problem

WiredTiger eviction is a background process that attempts to keep the cache below its configured high-water mark (default 95% of cache size). When reads and writes drive cache occupancy above this threshold faster than background eviction can drain it, application threads begin participating in foreground eviction — pausing to evict pages before completing their operations. This is the condition that converts a slow-cache-miss into a stalled application thread.

The failure mode on Atlas and self-managed deployments looks similar: read throughput drops, latency climbs, and CloudWatch or Atlas metrics show disk IOPS climbing while CPU stays flat. The traditional diagnosis suspects indexes — add an index, the IOPS should drop. It does not drop because the index pages are themselves not fitting in cache.

The core question: is the WiredTiger cache sized for your actual uncompressed working set, and is eviction pressure currently active?

How WiredTiger Cache Works

WiredTiger cache metrics are accessible through db.serverStatus():

db.serverStatus().wiredTiger.cache

Key fields to examine:

FieldWhat it measures
bytes currently in the cacheCurrent uncompressed bytes in cache
maximum bytes configuredConfigured cache ceiling
pages evicted by application threadsForeground eviction — application threads stalled for eviction
pages read into cacheCumulative physical reads from disk into cache
tracked dirty bytes in the cacheModified pages not yet flushed to disk

The ratio that matters most operationally:

cache fill ratio = bytes currently in cache / maximum bytes configured

A ratio consistently above 90–95% means background eviction is working hard to prevent foreground eviction. A ratio above 95% combined with nonzero pages evicted by application threads means foreground eviction is active and application threads are being paused.

Checking cache pressure:

let c = db.serverStatus().wiredTiger.cache;
print("Cache fill %:", Math.round(c["bytes currently in the cache"] / c["maximum bytes configured"] * 100));
print("App thread evictions:", c["pages evicted by application threads"]);

Cache sizing: MongoDB documentation specifies the default as the larger of 256 MB or (RAM - 1GB) * 0.5. On a 16 GB server, that is (16-1) * 0.5 = 7.5 GB. For a server dedicated to MongoDB, the documented guidance is to set wiredTigerCacheSizeGB to roughly 60% of available RAM, leaving headroom for OS page cache, sort operations, and connection overhead.

Configure via mongod.conf:

storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 10

The two-layer memory model: When MongoDB reads a document from disk, the OS page cache loads the compressed block. WiredTiger decompresses it into the internal cache. Both layers retain the data independently. On a cache miss in WiredTiger but a hit in OS page cache, the read is a decompression operation rather than a physical disk I/O — faster than a full disk read, but slower than a WiredTiger cache hit. Monitoring only disk IOPS can understate the actual working set pressure if the OS page cache is absorbing misses.

In Practice

The documented behavior of WiredTiger, as described in the MongoDB documentation chapter “WiredTiger Storage Engine,” is that the internal cache holds uncompressed document and index pages while on-disk storage uses compression. MongoDB documentation explicitly notes this asymmetry: “with compression, less data is stored on disk but the storage engine cache holds data in its uncompressed form.” This is the source of the common sizing mistake where teams provision RAM based on compressed disk size.

The db.serverStatus().wiredTiger.cache output is documented in the MongoDB Server Manual under “db.serverStatus() output — wiredTiger.” The field pages evicted by application threads is specifically called out in MongoDB documentation as an indicator of eviction pressure reaching foreground threads.

Where It Breaks

ScenarioWhat breaksWhy
Working set exceeds cacheRead IOPS spike; ops/sec dropsCache misses require physical disk reads after eviction
Read-heavy analytics scanning full collectionsNormal OLTP reads get evictedAnalytics scan floods cache with pages that are not reused
Uncompressed cache significantly larger than disk sizeUndersized WiredTiger cache despite adequate diskEngineers sized RAM for compressed footprint, not uncompressed working set

What to Do Next

  • Problem: WiredTiger cache is sized for compressed disk footprint, not the uncompressed working set — eviction pressure is causing application threads to stall on foreground eviction.
  • Solution: Check cache fill ratio and foreground eviction count via db.serverStatus().wiredTiger.cache; if fill ratio exceeds 90% consistently, increase wiredTigerCacheSizeGB to 60% of available RAM or upgrade instance size.
  • Proof: After resizing, monitor pages evicted by application threads dropping to near zero; ops/sec should stabilize and disk IOPS should drop.
  • Action: This week, run the cache fill ratio check above against any MongoDB deployment that has been showing elevated IOPS or latency — verify whether cache pressure is the underlying cause before adding indexes or upgrading storage.

The WiredTiger cache and the OS page cache are two separate memory pools with two separate capacities. Sizing only one correctly is not enough.