skip and limit in aggregation framework
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In MongoDB aggregation, "$skip" and "$limit" control how many documents continue through the pipeline. They are central to pagination and resource control, but performance depends heavily on stage order and sort strategy. Used carefully, they keep responses predictable; used blindly, they can create expensive scans on large collections.
What "$skip" and "$limit" Actually Do
"$skip" discards the first N documents from the current pipeline stream. "$limit" keeps only the first N documents and drops the rest.
Basic examples:
These stages act on the order established by previous stages. Without explicit "$sort", result order may be inconsistent across executions.
Correct Pagination Pattern
For page-based APIs, typical order is:
"$match"for filtering."$sort"for deterministic order."$skip"for offset."$limit"for page size.
Sorting by a stable key pair such as orderDate plus _id avoids duplicate or missing rows when timestamps tie.
Performance Implications
Large skip values can be expensive because MongoDB still traverses skipped documents. Even with indexes, high offsets may become slow for deep pages.
To improve:
- index fields used in
"$match"and"$sort". - keep page size bounded.
- consider keyset pagination for very deep navigation.
Keyset style avoids large offsets by using last-seen values:
This is often faster and more stable for high-volume feeds.
Stage Ordering Mistakes to Avoid
Placing "$skip" before a narrowing "$match" often increases work. Likewise, sorting after skip can produce incorrect pagination semantics.
Bad pattern:
Here MongoDB discards 5000 documents before applying status filter, which wastes effort and returns unexpected pages.
Practical API Design Notes
When exposing pagination in APIs:
- cap maximum
limit. - validate non-negative
skip. - return metadata such as page size and next cursor.
- include deterministic sort keys in every paged query.
For analytics endpoints, consider separate count queries or a "$facet" pipeline when you need both data and total count in one call.
Common Pitfalls
- Using
"$skip"without deterministic"$sort". - Deep offset pagination on large collections causing slow responses.
- Applying
"$skip"before selective"$match"and increasing scan cost. - Allowing unbounded
"$limit"values in public APIs. - Assuming skip-limit pagination is always correct under rapidly changing data.
Summary
"$skip"discards leading documents and"$limit"caps output size.- Always pair pagination with explicit deterministic sorting.
- Stage order strongly affects both correctness and performance.
- Large offsets are costly, so consider keyset pagination for deep pages.
- Validate pagination inputs and enforce safe API limits. Monitor slow query logs after pagination changes to confirm real production impact.
Related reading
- Sleep Command in T-SQL?
- Slicing a tensor by using indices in Tensorflow
- SNIReadSyncOverAsync Performance issue
- Solandra vs. ElasticSearch
- Solr shard distribution data not distributed evenly
- SolrCloud index replication
- Solving a communications link failure with JDBC and MySQL
- Solving a communications link failure with JDBC and MySQL

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.