DOSSIER 07 • B-TREE WORKING SET REDUCTION

MongoShard Dossier: Shrinking WiredTiger B-Tree Index RAM via ESR & Partial Filters

Dossier Code
ESR-INDEX-RAM
WT Cache Metric
ESR + Partial Filter
Eviction Target
Prune 0-Hit B-Trees
Storage & Compression
Zero Blocking $sort • Prefix Compression

In our MongoShard capacity audits, bloated single-field and duplicate prefix indexes are the #1 cause of oversized Atlas tiers — learn how ESR ordering and partialFilterExpression trim WiredTiger RAM demand before upgrading hardware.

MongoShard Index Mechanics: Why Redundant B-Trees Multiply Write IOPS & Starve Cache

Every secondary index on a MongoDB collection requires B-Tree maintenance on mutations and competes for permanent residency inside WiredTiger internal RAM. Collections carrying a dozen ad-hoc single-field indexes frequently consume more cache for index pages than for hot documents, while poorly ordered keys still trigger 100 MB blocking in-memory sorts when violating Equality → Sort → Range (ESR).

MongoShard WiredTiger 0.5 * (RAM - 1GB) uncompressed B-Tree internal cache vs Linux Zstd compressed filesystem cache diagram (compound-index-ram-optimization)
Figure 1 — MongoShard deterministic memory boundary: WiredTiger decompresses BSON pages inside 50% × (RAM − 1 GB) while Linux buffers Zstd blocks in the remaining host RAM.

MongoShard $indexStats Audit Query & Partial ESR Index Definition

MongoShard reference snippet (compound-index-ram-optimization) — verify host RAM and XFS mount before restarting mongod.

// 1. Audit zero-hit or redundant indexes across your primary collection (mongosh)
db.orders.aggregate([
  { $indexStats: {} },
  { $project: { name: 1, accesses: "$accesses.ops", since: "$accesses.since" } },
  { $sort: { accesses: 1 } }
]);

// 2. Replace full-table index with ESR + partialFilterExpression to index only active rows
db.orders.createIndex(
  { tenantId: 1, createdAt: -1, totalCents: 1 }, // Equality -> Sort -> Range
  {
    name: "idx_esr_active_orders",
    partialFilterExpression: { status: { $in: ["pending", "processing"] } }
  }
);

MongoShard Capacity Matrix for DOSSIER 07 • B-TREE WORKING SET REDUCTION (2026-11-12 Public Rates)

Each hardware tier below follows our MongoShard (RAM − 1 GB) × 0.50 calculation and cites public vendor pricing retrieved on 2026-11-12 from UltaHost (https://ultahost.com/vps-hosting) and InterServer (https://www.interserver.net/vps/).

Workload Scale / Node Class WiredTiger Cache Active Working Set Fit Reference Host Tier (2026-11-12)
Unpruned Schema (60 GB Bloated Indexes) ~80+ GB WT Cache Needed Forces 192 GB+ / Multi-Shard Atlas M80+ ($5,380+/mo list)
After Prefix Prune & ESR (24 GB Indexes) 31.5 GB WT Cache (64GB Node) Fits Single 64 GB Replica Set UltaHost VDS 64GB ($95/mo/node)
With Partial Active Filter (10 GB Indexes) 15.5 GB WT Cache (32GB Node) Fits Single 32 GB Replica Set UltaHost VDS 32GB / Hostinger KVM 8

MongoShard Production Deployment Checklist (ESR-INDEX-RAM)

  1. Eliminate left-prefix duplicates: compound index { tenantId: 1, status: 1 } already covers queries filtering on { tenantId: 1 }.
  2. Structure compound keys strictly in Equality → Sort → Range (ESR) sequence to prevent blocking in-memory sort stages.
  3. Apply partialFilterExpression so archived historical documents (90% of disk rows) omit secondary B-Tree entries.
  4. Use db.collection.hideIndex("name") on MongoDB 8.0 for 48 hours to validate query plans safely before dropping an index.

Inspect UltaHost Specs for MongoShard ESR-INDEX-RAM ↗ Compare InterServer Rates for MongoShard ESR-INDEX-RAM ↗ Load Preset in MongoShard Calculator →

MongoShard Technical FAQ: DOSSIER 07 • B-TREE WORKING SET REDUCTION

How does MongoShard treat prefixCompression when calculating B-Tree index RAM?

Unlike collection Zstd block compression (which decompresses inside WiredTiger cache), storage.wiredTiger.indexConfig.prefixCompression stays compressed in both disk blocks and WiredTiger internal RAM by default in MongoDB 8.0.

What safe index removal workflow does MongoShard recommend for live SaaS databases?

Always invoke db.collection.hideIndex() first and observe slow-query logs across two full business cycles; if a weekly job regresses, unhideIndex() restores query performance immediately without a multi-hour index rebuild.