INTRO
OLAP warehouses exist for a reason - but many MERN teams still need “good enough” reporting in-app. Aggregation pipelines can summarize tickets per day or revenue per category if you respect indexes and document sizes. I start with `$match` early to shrink working set.
$match and $project early
Push selective filters into `$match` using indexed fields (tenant, date range). Project only fields needed downstream to reduce memory.
Explain plans in staging with representative data volumes - dashboards that work on 1k rows may die at 1M.
code-snippet.typescript
const rows = await Order.aggregate([
{ $match: { tenantId, createdAt: { $gte: start, $lte: end } } },
{ $group: { _id: '$status', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
])$lookup cost and alternatives
`$lookup` is a join; abuse it and you recreate RDBMS pain without constraints. Denormalize small display fields at write time when reads are hot.
For cross-collection reports that hammer CPU, schedule nightly rollups into summary collections.
Exports and hard limits
CSV export endpoints need caps and streaming. Never `find()` unbounded into memory.
KEY TAKEAWAYS
“Filter early on indexed fields; project late fields away.”
- 02
Treat `$lookup` as expensive; denormalize or precompute when needed.
- 03
Stream large exports; enforce limits.
CONCLUSION
Closing thought
Mongo aggregations are powerful and easy to misuse. Profile with real data size, precompute when interactive latency suffers, and know when to graduate metrics to a warehouse. Ready to talk scope? Use Contact — or browse Services for fit.
CONTINUE
Related pages
UP NEXT
Deploying MERN Apps: Vercel, Render, and Railway
Where I host the React/Next front, where the Express API fits, and how to avoid calling a sleeping free-tier DB from a serverless function.
Read next article