Sorting in MongoDB aggregations seems straightforward until your query slows your server to a crawl. Why? The $sort stage can be a performance bottleneck, especially on large datasets. This post explains why and shares proven strategies to optimize sorting, keeping your queries fast and efficient. (Based on MongoDB 8.0 documentation.)
Why $sort can Hurt Performance?
The $sort stage in MongoDB’s aggregation pipeline is blocking. It must process all input documents before sorting and passing them to the next stage. For large datasets, this can lead to:
- High memory usage: Sorting loads documents into memory. In MongoDB versions before 4.4, $sort and $group stages have a 100MB memory limit unless allowDiskUse is enabled. Exceeding this causes disk spills, slowing performance.
- Disk spills: In MongoDB 4.4+, allowDiskUse (enabled by default in many cases) allows sorting to spill to disk, but this degrades performance due to disk I/O.
- Slow responses: Sorting millions of documents without optimization can take seconds or longer.
Let’s explore how to sort smarter.
3 Ways to Optimize $sort Stage Performance
1.Use an Index to Support Sorting
Indexes allow MongoDB to retrieve documents in the desired sort order, avoiding costly in-memory sorting. For example:
// Create a compound index
db.orders.createIndex({ status: 1, createdAt: -1 });
// Run the aggregation
db.orders.aggregate([
{ $match: { status: "delivered" } },
{ $sort: { createdAt: -1 } }
]);How it helps: MongoDB uses the index to fetch pre-sorted documents, reducing memory usage and avoiding an in-memory sort. Ensure the $match stage filters on fields included in the index (e.g., status) for best results.
Collation Note: If sorting with collation (e.g., { $sort: { name: 1, collation: { locale: “en”, strength: 2 } } }), create the index with the same collation to avoid in-memory sorting.
Caution: Indexes speed up reads but increase storage and slow writes. Use db.collection.stats() to monitor index size and only create indexes for frequent queries.
Tip:đź§Ş Try Indexes Safely in Mongo Pilot
Mongo Pilot lets you:
- âś… Run your query
- 📊 See query stats and performance with and without an index experiment
- Apply or remove the index experiment
Benchmark and validate the impact before adding it to production? You can do it with Mongo Pilot, a smart MongoDB GUI:
Read our guide about MongoDB Indexes
2.Use $limit Strategically
If you only need the top N results, use $limit to reduce the dataset. The placement of $limit matters:
With an index: Place $sort before $limit to fetch only the top N sorted documents efficiently (a “top-k” sort). For example, to get the 100 most recent delivered orders:
db.orders.createIndex({ status: 1, createdAt: -1 });
db.orders.aggregate([
{ $match: { status: "delivered" } },
{ $sort: { createdAt: -1 } },
{ $limit: 100 }
]);Without an index: As a fallback, place $limit before $sort to reduce the dataset, but note that MongoDB still sorts all limited documents, which can be slow for large limits (e.g., 5000):
db.orders.aggregate([
{ $match: { status: "delivered" } },
{ $limit: 5000 },
{ $sort: { createdAt: -1 } }
]);How it helps: $limit reduces the number of documents processed, saving memory and CPU. With an index, $sort + $limit is highly efficient.
3.Reduce Data Before Sorting
Push heavy filtering or projection stages like $match, $project, or $group before $sort to minimize the dataset. For example, for a dashboard showing the 50 most recent high-value orders:
db.orders.createIndex({ status: 1, total: 1, createdAt: -1 });
db.orders.aggregate([
{ $match: { status: "delivered", total: { $gt: 100 } } },
{ $project: { _id: 0, userId: 1, total: 1, createdAt: 1 } },
{ $sort: { createdAt: -1 } },
{ $limit: 50 }
]);How it helps:
- $match filters out irrelevant documents early.
- $project excludes unnecessary fields (e.g., large nested objects), reducing memory usage.
- Sorting a smaller dataset is faster and less resource-intensive.
Note: Other stages like $group, $lookup, or $unwind can also consume memory or CPU. For example, $group may require disk spills if not indexed, and $lookup can inflate the dataset. Optimize these stages alongside $sort and use .explain() to analyze the entire pipeline.
Automatic Optimizations: MongoDB may combine adjacent $match or $project stages to reduce the dataset before $sort, boosting performance. Structure your pipeline to maximize these optimizations.
Also read > Top 10 MongoDB Aggregation Operators You Should Master
Controlling Disk Usage
Enable allowDiskUse: true to allow $sort to spill to disk if memory limits are exceeded:
db.orders.aggregate([...], { allowDiskUse: true });However, disk spills slow performance due to disk I/O. Prioritize indexes and dataset reduction to minimize reliance on disk spills.
Diagnosing Sort Performance
Use .explain(“executionStats”) to analyze your pipeline:
db.orders.aggregate([...]).explain("executionStats");Or visually using Mongo Pilot query stats

Look for:
- “stage”: “SORT”: Indicates an in-memory sort, which is costly without an index.
- “usedDisk”: true: Shows disk spills (if applicable), signaling performance issues.
- “totalDocsExamined”: High values mean too many documents are processed.
- “indexName”: Confirms if an index was used.
Sharded Clusters
In sharded environments, ensure $sort uses an index to avoid sorting on the primary shard, which can bottleneck performance. Combining $sort with $limit and an index is especially effective for fetching top results efficiently.
Pipeline Limits
Keep pipelines concise, as MongoDB limits pipelines to 1000 stages. Overly complex pipelines may also hit memory or result size limits, especially without optimization. Use Mongo Pilot aggregation builder to diagnose, inspect the output of each stage, and search for specific occurences.
Read also > 6 Common MongoDB Query Mistakes (and How to Fix Them)
Final Notes
Optimize $sort stage in MongoDB aggregations by:
- Using indexes to avoid in-memory sorting (e.g., { status: 1, createdAt: -1 }).
- Applying $limit after $sort with an index for top-k results or before $sort without an index (less efficient).
- Reducing data with $match or $project before sorting.
- Diagnosing issues with .explain(“executionStats”) and tools like Mongo Pilot.
- Ensuring indexes match collation and sharded cluster requirements.
- Minimizing disk spills with allowDiskUse: true as a last resort.
-> Test your MongoDB Knowledge by taking our interactive Quiz Challenge
