Fix MongoDB Sort Exceeded Memory Limit: Root Causes and Minimal Fixes
Quick Answer
- Conclusion: The
Sort exceeded memory limiterror occurs when MongoDB's in-memory sort exceedsinternalQueryMaxBlockingSortMemoryUsageBytes(100MB default in 4.2+, 32MB in older versions). The preferred fix is creating a supporting index;allowDiskUseis a temporary workaround. - First checks: Run
explain()on the failing query to see if an index is being used. IfSORTstage appears in the execution plan, an index is missing. - Minimal fix: Create a compound index matching your sort fields, e.g.,
db.orders.createIndex({ status: 1, createdAt: -1 }). For aggregation pipelines, add{ allowDiskUse: true }as a temporary workaround. - Version boundary:
cursor.allowDiskUse(true)forfind()queries is only available in MongoDB 4.4+. For older versions, index creation or server-level memory limit adjustment are the only options.
What Problem It Solves
MongoDB limits how much RAM a single blocking sort operation can consume. When a query or aggregation pipeline needs to sort more data than the configured threshold, MongoDB aborts the operation with an error like:
MongoError: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting.
This error typically appears in production environments handling large datasets:
- E-commerce order queries: Sorting thousands of orders by date or amount
- Log analysis systems: Aggregating and sorting millions of log entries
- User behavior analytics: Sorting large event streams by timestamp
- Real-time reporting: Filtering and sorting large datasets for dashboards
The error is a safety mechanism, not a bug. It prevents a single query from exhausting server memory and destabilizing the entire MongoDB instance.
Root Cause Analysis
MongoDB performs sorting in one of two ways:
- Index-based sort: If a query can use an index that already provides the requested sort order, MongoDB returns documents directly in that order. No additional memory is consumed.
- Blocking in-memory sort: If no suitable index exists, MongoDB must load all matching documents into memory, sort them, and then return results. This is called a "blocking sort" because the entire result set must be materialized before any document is returned.
The memory limit for blocking sorts is controlled by the server parameter internalQueryMaxBlockingSortMemoryUsageBytes:
| MongoDB Version | Default Limit |
|---|---|
| 4.0 and earlier | 32MB (33554432 bytes) |
| 4.2+ | 100MB (104857600 bytes) |
When the sort operation exceeds this threshold, MongoDB throws the error instead of spilling to disk by default. This is intentional—disk-based sorting can cause significant performance degradation.
Minimal Working Configuration
Fix 1: Create a Supporting Index (Preferred)
The most effective and permanent solution is to create an index that matches your sort pattern. For a query like:
JAVASCRIPTdb.orders.find({ status: "shipped" }).sort({ createdAt: -1 })
Create a compound index:
JAVASCRIPTdb.orders.createIndex({ status: 1, createdAt: -1 })
The index order matters: equality fields first, then sort fields. For aggregation pipelines, the same principle applies:
JAVASCRIPTdb.orders.aggregate([ { $match: { status: "shipped" } }, { $sort: { createdAt: -1 } } ])
The same index { status: 1, createdAt: -1 } will eliminate the blocking sort.
Fix 2: Use allowDiskUse (Temporary Workaround)
For aggregation pipelines:
JAVASCRIPTdb.orders.aggregate( [ { $match: { status: "shipped" } }, { $sort: { createdAt: -1 } } ], { allowDiskUse: true } )
For find() queries in MongoDB 4.4+:
JAVASCRIPTdb.orders.find({ status: "shipped" }).sort({ createdAt: -1 }).allowDiskUse(true)
Fix 3: Adjust Server Memory Limit (Use with Caution)
To increase the global sort memory limit:
JAVASCRIPTdb.adminCommand({ setParameter: 1, internalQueryMaxBlockingSortMemoryUsageBytes: 524288000 // 500MB })
This affects all queries on the server and can increase memory pressure. Monitor server memory usage carefully after applying.
Parameters and Environment Variables
| Parameter | Scope | Description |
|---|---|---|
allowDiskUse | Per-query | Enables disk-based sorting for aggregation pipelines or find() queries (4.4+) |
internalQueryMaxBlockingSortMemoryUsageBytes | Server-wide | Sets the maximum memory (in bytes) for blocking sort operations. Default: 104857600 (100MB) in 4.2+, 33554432 (32MB) in older versions |
cacheSizeGB | WiredTiger storage engine | Configures the WiredTiger internal cache size. Larger cache can improve performance for large sort operations but does not directly change the sort memory limit |
For cacheSizeGB, set it in the MongoDB configuration file:
YAMLstorage: wiredTiger: engineConfig: cacheSizeGB: 4
Common Errors and Fixes
| Error Message | Root Cause | Fix |
|---|---|---|
Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting | 100MB limit exceeded (4.2+) | Create supporting index, or use allowDiskUse: true in aggregation, or cursor.allowDiskUse(true) in 4.4+ |
Sort exceeded memory limit of 33554432 bytes, but did not opt in to external sorting | 32MB limit exceeded (pre-4.2) | Add index, use allowDiskUse, optimize pipeline order ($match before $sort), use $project to reduce document size |
Executor error during find command :: caused by :: Sort exceeded memory limit | find() query without index support | Use explain() to verify execution plan; add index, or use .allowDiskUse(true) in 4.4+ |
Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit | Legacy error message | Add index or use allowDiskUse; ensure $match precedes $sort in pipelines and use $limit to constrain result size |
Production Notes and Security Checks
Performance Considerations
- Index optimization is always preferred over
allowDiskUse. Index-based sorts avoid disk I/O and return results faster. allowDiskUseincreases disk I/O and latency. Ensure sufficient disk space and monitor I/O metrics when using it.- Adjusting
internalQueryMaxBlockingSortMemoryUsageBytesaffects all queries. This can cause memory pressure and server instability if set too high. - Index creation impacts write performance and consumes storage. Create indexes during maintenance windows.
Security and Operational Checks
- Restrict
allowDiskUseusage: Malicious queries could consume excessive disk space. Consider application-level validation to prevent abuse. - Control
setParameteraccess: Only grantsetParameterprivileges to trusted administrators. - Monitor slow queries: Use MongoDB Profiler or Atlas Performance Advisor to identify queries that trigger memory sorting.
- Test before production: Validate index and configuration changes in a staging environment first.
- Sharded clusters: For sharded deployments, ensure indexes align with the shard key. Otherwise, sorting may still require memory even with indexes.
Pipeline Optimization Tips
Reorder aggregation stages to reduce data before sorting:
JAVASCRIPT// Instead of: db.collection.aggregate([ { $sort: { createdAt: -1 } }, { $match: { status: "shipped" } } ]) // Do: db.collection.aggregate([ { $match: { status: "shipped" } }, { $sort: { createdAt: -1 } } ])
Use $project to strip unnecessary fields before sorting:
JAVASCRIPTdb.collection.aggregate([ { $match: { status: "shipped" } }, { $project: { createdAt: 1, amount: 1 } }, { $sort: { createdAt: -1 } } ])
FAQ
Q: Why is MongoDB's default sort memory limit 100MB or 32MB?
A: MongoDB limits in-memory sorting to prevent a single query from consuming excessive RAM and destabilizing the server. The 100MB default applies to MongoDB 4.2+ (internalQueryMaxBlockingSortMemoryUsageBytes), while 32MB was the default in 4.0 and earlier. You can adjust this via setParameter, but index optimization is the recommended approach to avoid memory sorting entirely.
Q: What's the difference between allowDiskUse and index optimization? How do I choose?
A: Index optimization is the preferred solution because MongoDB returns documents directly in index order, completely avoiding memory sorting and delivering the fastest query performance. allowDiskUse is a temporary workaround that spills sort data to disk, increasing disk I/O and latency. Choose indexes for frequent, large-scale queries; use allowDiskUse for occasional complex aggregations where index creation isn't practical.
Q: Does find() support allowDiskUse before MongoDB 4.4?
A: No. Before MongoDB 4.4, allowDiskUse was only available for aggregation pipelines (aggregate()). For find() queries on older versions, the only solutions are creating a supporting index or adjusting the server-level memory limit. Upgrading to 4.4+ enables cursor.allowDiskUse(true) for find() queries.