Introduction WiredTiger, MongoDB's default storage engine, uses an in-memory cache to buffer reads and writes. When the cache fills faster than the eviction thread can flush dirty pages to disk, write operations stall waiting for cache space. This "eviction thrashing" causes write latency spikes and throughput drops.
Symptoms - Write latency spikes from milliseconds to seconds during peak load - MongoDB logs show `WT_CACHE: waiting for eviction` messages - `db.serverStatus().wiredTiger.cache` shows `eviction server stuck` or high `tracked dirty bytes` - `current queued evictions` consistently above 100 - CPU usage shows high `iowait` percentage during write stalls
Common Causes - `wiredTigerCacheSizeGB` too small for the write working set - Write pattern generating many small random writes instead of sequential - Insufficient disk IOPS causing eviction threads to fall behind - Large unindexed writes causing full collection scans in cache - Eviction threads configured too conservatively
Step-by-Step Fix 1. **Check WiredTiger cache statistics**: ```javascript // In mongosh var cache = db.serverStatus().wiredTiger.cache; print("Cache used: " + cache["bytes currently in the cache"] / 1024 / 1024 / 1024 + " GB"); print("Cache max: " + cache["maximum bytes configured"] / 1024 / 1024 / 1024 + " GB"); print("Dirty bytes: " + cache["tracked dirty bytes in the cache"] / 1024 / 1024 + " MB"); print("Eviction server stuck: " + cache["eviction server stuck"]); print("Pages queued for eviction: " + cache["pages queued for eviction"]); ```
- 1.Increase the WiredTiger cache size:
- 2.```yaml
- 3.# /etc/mongod.conf
- 4.storage:
- 5.wiredTiger:
- 6.engineConfig:
- 7.cacheSizeGB: 8 # Set to ~50% of available RAM
- 8.
` - 9.```bash
- 10.sudo systemctl restart mongod
- 11.
` - 12.Tune eviction thresholds for write-heavy workloads:
- 13.```yaml
- 14.storage:
- 15.wiredTiger:
- 16.engineConfig:
- 17.configString: "eviction=(threads_max=8),eviction_dirty_target=5,eviction_dirty_trigger=20"
- 18.
` - 19.Add missing indexes to reduce cache pressure from unindexed writes:
- 20.```javascript
- 21.// Find unindexed writes in the profiler
- 22.db.system.profile.find({
- 23."op": "update",
- 24."planSummary": { $ne: "IXSCAN" }
- 25.}).sort({ ts: -1 }).limit(10);
// Add the missing index db.collection.createIndex({ status: 1, updated_at: -1 }); ```
- 1.Batch writes to reduce individual cache pressure:
- 2.```javascript
- 3.// Instead of individual inserts
- 4.// BAD: for (let i = 0; i < 10000; i++) db.collection.insertOne({...})
// GOOD: bulk write
const bulk = db.collection.initializeUnorderedBulkOp();
for (let i = 0; i < 10000; i++) {
bulk.insert({ data: item_${i}, created: new Date() });
}
bulk.execute();
```
- 1.Monitor disk IOPS to ensure eviction can keep up:
- 2.```bash
- 3.iostat -x 1 10
- 4.# Check %util on the MongoDB data disk - if consistently > 80%, disk is bottleneck
- 5.# Check await - if > 10ms, disk latency is too high for eviction
- 6.
`