intermediate
Collections
Separate collections by ownership, query needs, validation rules, lifecycle, and sharding expectations.
Collections are namespaces for documents with shared query, validation, and lifecycle expectations — not just "tables with a different name." Split or merge collections by ownership, access pattern, retention, and sharding key compatibility.
// Separate collections when lifecycle and indexes diverge
db.orders.insertOne({ ... }) // hot transactional data
db.order_events.insertOne({ ... }) // append-only audit trail
| Split collections when | Keep together when | |------------------------|------------------| | Different TTL or archival policy | Always queried as one unit | | Distinct shard keys or cardinality | Same indexes serve all queries | | Independent write rates | Shared validation and ownership | | Security / tenancy boundaries | Document growth stays bounded |
Collection-level options matter: `validator` for schema rules, `collation` for locale-aware sorting, capped collections for fixed-size logs, and time series collections for metrics-shaped data.
On interviews: justify collection boundaries with query shapes and operational policies, not folder aesthetics.
Common pitfalls: one giant collection with unrelated document shapes; separate collections that always require application-side joins; ignoring shard key choice at collection design time; mixing PII and public data without access separation.
The trade-off is operational isolation versus join cost — more collections simplify scaling and policies but push relationship work into the application or aggregation pipeline.
Checklist:
- Map each collection to an owner and access pattern.
- State validation, TTL, and archival policy per collection.
- Explain shard key implications early.
- Name when `$lookup` cost is acceptable.