Classic MongoDB Traps
Never use $where in production. It executes JavaScript in the database — extremely slow (can't use indexes) and a security risk.
$lookup creates an array — always $unwind after. Forgetting to unwind leaves you with an array field instead of embedded object. Use preserveNullAndEmptyArrays: true to keep unmatched docs.
Unbounded arrays are dangerous. Embedding an ever-growing array (like all comments on a viral post) hits the 16MB document limit. Use a separate collection once count can grow large.
$set vs replaceOne. Forgetting $set in updateOne replaces the entire document except _id. Always use update operators ($set, $inc, etc.) unless you want a full replace.
Mongoose .lean() for read performance. Without .lean(), Mongoose wraps every doc in a full Mongoose document (with methods, virtuals). Use .lean() for read-only queries — 3-10x faster.
Transactions require Replica Set. Multi-document transactions don't work on standalone MongoDB instances. Need at least a 1-node replica set even in development.
Case-sensitive queries. MongoDB queries are case-sensitive by default. Use $regex: /pattern/i or store normalized lowercase in a separate field for case-insensitive search.
null vs missing fields. { field: null } matches documents where field is null AND where field doesn't exist. Use $exists to distinguish them.