MongoDB $limit Stage

Beginner
⏱️ 9 min read
📚 Updated: Jul 2026
🎯 5 Examples
Aggregation

What You’ll Learn

The $limit stage keeps only the first N documents from the current pipeline and drops the rest—essential for top-10 lists, paginated APIs, and trimming heavy intermediate results before expensive downstream stages.

01

Cap output

First N docs.

02

Top-N lists

After $sort.

03

Pagination

$skip + $limit.

04

After $group

Top categories.

05

Performance

Less downstream work.

06

vs $sample

Ordered vs random.

Definition and Usage

$limit is an aggregation stage that restricts how many documents continue to the next stage. It is the pipeline equivalent of .limit(N) on a find cursor—simple, fast, and one of the most commonly used stages in production pipelines.

💡
Beginner tip

$limit alone does not sort. For “top 5 highest scores,” always write $sort first, then $limit: 5. The limit stage takes whatever order the previous stage produced.

Use $limit after filtering ($match), sorting ($sort), or grouping ($group) when the UI or API only needs a subset. Pair with $skip for offset-based pagination.

📝 Syntax

$limit accepts a single positive integer:

mongosh
{ $limit: <positive integer> }

Syntax Rules

  • Positive integerN must be ≥ 0. { $limit: 0 } returns no documents.
  • First N only — passes documents in the order received from the prior stage.
  • Sort first — for ranked results, place $sort immediately before $limit.
  • Pagination — typical order: $match$sort$skip$limit.
  • Fewer than N — if only 3 docs arrive and $limit is 10, all 3 pass through.
  • Top-k optimization — MongoDB may optimize adjacent $sort + $limit together.
mongosh
db.articles.aggregate([
  { $match: { published: true } },
  { $sort: { views: -1 } },
  { $limit: 10 }
])

⚡ Quick Reference

QuestionAnswer
What it doesPasses first N documents; discards the rest
Syntax{ $limit: N }
Top-N pattern$sort then $limit
Page size 20, page 3$skip: 40, $limit: 20 (0-based skip)
find() equivalentdb.col.find().limit(N)
Random subsetUse $sample, not $limit
Top 5
{ $sort: { score: -1 }},
{ $limit: 5 }

Leaderboard

Page 2 (size 10)
{ $skip: 10 },
{ $limit: 10 }

Offset paging

After $group
{ $sort: { total: -1 }},
{ $limit: 3 }

Top categories

Empty result
{ $limit: 0 }

Zero docs out

🧰 Parameters

$limit has a single argument—the maximum number of documents to pass through:

N Required

Non-negative integer. MongoDB stops after emitting N documents from this stage’s input stream.

{ $limit: 25 }
N = 0 Edge case

Valid syntax that produces an empty result set—occasionally used in conditional pipeline patterns.

{ $limit: 0 }
→ []
With $skip Pattern

Skip offsets the window; limit sets window size. Formula: $skip: (page - 1) * pageSize.

$skip: 20, $limit: 10
→ rows 21–30
With $sort Pattern

Sort defines ranking; limit trims to top or bottom N. Index the sort field for performance.

$sort: { date: -1 }
$limit: 5

Examples Gallery

Sample articles collection—basic cap, top viewed posts, paginated feed, top revenue categories after $group, and nearest places after $geoNear.

📚 Getting Started

Blog articles for limit and pagination labs.

Example 1 — Articles collection

mongosh
db.articles.drop()
db.articles.insertMany([
  { title: "Intro to MongoDB",     category: "Database", views: 12400, published: true,  createdAt: ISODate("2025-01-15") },
  { title: "Aggregation Basics",   category: "Database", views: 8900,  published: true,  createdAt: ISODate("2025-02-20") },
  { title: "Node.js + MongoDB",    category: "Backend",  views: 15200, published: true,  createdAt: ISODate("2025-03-05") },
  { title: "Indexing Strategies",  category: "Database", views: 6700,  published: true,  createdAt: ISODate("2025-04-10") },
  { title: "Draft: Sharding",      category: "Database", views: 0,     published: false, createdAt: ISODate("2025-05-01") },
  { title: "REST API Design",      category: "Backend",  views: 11300, published: true,  createdAt: ISODate("2025-05-18") },
  { title: "Schema Validation",    category: "Database", views: 5400,  published: true,  createdAt: ISODate("2025-06-02") },
  { title: "Express Middleware",   category: "Backend",  views: 7800,  published: true,  createdAt: ISODate("2025-06-25") }
])

db.articles.createIndex({ views: -1 })
db.articles.createIndex({ published: 1, createdAt: -1 })

How It Works

Eight articles with views, category, and published flags—enough data to see how $limit trims results after filter and sort stages.

Example 2 — Return only 3 documents

mongosh
db.articles.aggregate([
  { $match: { published: true } },
  { $limit: 3 },
  { $project: { title: 1, views: 1, _id: 0 } }
])

// Returns exactly 3 published articles
// Order is NOT guaranteed without $sort
// → arbitrary first 3 in scan/processing order

How It Works

$limit stops the pipeline after N documents—downstream stages process fewer rows. Without $sort, which three you get depends on internal processing order, not business logic.

Example 3 — Top 3 most-viewed articles

mongosh
db.articles.aggregate([
  { $match: { published: true } },
  { $sort: { views: -1 } },
  { $limit: 3 },
  {
    $project: {
      title: 1,
      views: 1,
      rank: { $literal: "top" },
      _id: 0
    }
  }
])

/* Expected top 3 by views:
   1. Node.js + MongoDB      (15200)
   2. Intro to MongoDB       (12400)
   3. REST API Design        (11300)
*/

How It Works

This is the classic leaderboard pattern: $match filters, $sort ranks, $limit keeps the head of the list. MongoDB can apply top-k optimization when sort and limit are adjacent.

📈 Practical Patterns

Pagination, grouped summaries, and geo nearest-N.

Example 4 — Paginated feed (page 2, 3 per page)

mongosh
const page = 2
const pageSize = 3
const skip = (page - 1) * pageSize  // → 3

db.articles.aggregate([
  { $match: { published: true } },
  { $sort: { createdAt: -1 } },
  { $skip: skip },
  { $limit: pageSize },
  { $project: { title: 1, createdAt: 1, _id: 0 } }
])

// Page 1: skip 0,  limit 3 → newest 3
// Page 2: skip 3,  limit 3 → articles 4–6
// Page 3: skip 6,  limit 3 → articles 7–9 (if exist)

// For total count in same query, use $facet:
// items: [{ $skip }, { $limit }], meta: [{ $count: "total" }]

How It Works

$skip advances the window; $limit sets page size. Always sort by a unique or stable key (often createdAt + _id) so pages do not shift when new documents insert between requests.

Example 5 — Top 2 categories by total views (after $group)

mongosh
db.articles.aggregate([
  { $match: { published: true } },
  {
    $group: {
      _id: "$category",
      totalViews: { $sum: "$views" },
      articleCount: { $sum: 1 }
    }
  },
  { $sort: { totalViews: -1 } },
  { $limit: 2 },
  {
    $project: {
      category: "$_id",
      totalViews: 1,
      articleCount: 1,
      _id: 0
    }
  }
])

// Also common after $geoNear:
// { $geoNear: { ... } }, { $limit: 5 }  → nearest 5 places

// vs $sample: random 5 docs, not ordered top 5

How It Works

$group shrinks many articles into few category rows; $sort + $limit picks the top two. The same pattern works after $geoNear for “nearest 5 locations” on a map.

🧠 How $limit Works

1

Input stream

Documents arrive from the previous stage in whatever order that stage produced.

Input
2

Counter stops at N

$limit emits documents one by one until the count reaches N, then stops reading further input.

Cap
3

Downstream continues

Later stages ($project, $lookup) process only the limited set—saving CPU and memory.

Pass
=

Bounded result

At most N documents reach the client—ideal for APIs with fixed page sizes or dashboard widgets.

📝 Notes

  • $limit does not sort—pair with $sort for ranked top-N results.
  • { $limit: 0 } is valid and returns zero documents.
  • Large $skip values (deep pagination) scan and discard many docs—consider cursor-based paging for page 100+.
  • MongoDB may fuse $sort + $limit into an efficient top-k plan when an index supports the sort.
  • In $facet, each sub-pipeline can have its own $limit (e.g. paginated items vs full count).
  • Previous topic: $indexStats. Next: $listLocalSessions.

Conclusion

$limit is a small stage with big impact: cap results, build top-N lists with $sort, and paginate with $skip for API-friendly output sizes.

Remember that order matters—limit takes the first N in pipeline order. Next: $listLocalSessions for session diagnostics.

💡 Best Practices

✅ Do

  • Always $sort before $limit when ranking matters
  • Index fields used in $match + $sort for top-N queries
  • Use stable sort keys (_id as tiebreaker) for consistent pagination
  • Place $limit before expensive stages like $lookup when possible
  • Combine with $facet when the API needs rows + total count

❌ Don’t

  • Expect meaningful “top N” without a preceding $sort
  • Use very large $skip on big collections without performance testing
  • Confuse $limit with $sample for random selection
  • Assume $limit alone reduces collection scan work without sort/index support
  • Forget that fewer than N input docs means a shorter result—not an error

Key Takeaways

Knowledge Unlocked

Five things to remember about $limit

Use these points whenever you cap or paginate aggregation results.

5
Core concepts
📈 02

$sort first

Meaningful top-N.

Pattern
📄 03

$skip + $limit

Pagination.

API
04

Top-k opt

Sort + limit fuse.

Perf
🎲 05

vs $sample

Ordered vs random.

Compare

❓ Frequently Asked Questions

$limit passes only the first N documents from its input to the next pipeline stage and discards the rest. Use it to cap result size—for example, return the top 10 rows after $sort or the first page of a paginated API.
{ $limit: <positive integer> }. Example: { $limit: 5 } returns at most five documents. If fewer than N documents arrive from the prior stage, you get all of them.
Yes, when you need a meaningful top-N—such as newest orders or highest scores. Without $sort, $limit returns an arbitrary first N documents (often collection scan order), which is rarely what you want for ranked lists.
Combine $skip and $limit: page 1 → { $skip: 0 }, { $limit: 20 }; page 2 → { $skip: 20 }, { $limit: 20 }. Always $sort first for consistent pages. For large offsets, consider cursor-based pagination instead of high $skip values.
$limit takes the first N documents in current pipeline order. $sample randomly selects N documents (or all if the collection is smaller). Use $limit for ranked or ordered slices; $sample for random subsets.
It can—especially after $sort when MongoDB applies top-k optimization, or after $match/$sort on an indexed field. Placing $limit early reduces work for downstream stages, but only when earlier stages already produce the correct ordering.
Did you know?

When $sort and $limit are adjacent, MongoDB can use a top-k optimization that avoids sorting the entire collection—especially effective with a supporting index. For deep pagination, cursor-based approaches (filtering by _id > lastSeenId) often outperform large $skip values. See the official $limit docs.

Continue the Stages Series

Cap results with $limit, then explore sessions with $listLocalSessions.

Next: $listLocalSessions →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful