When designing schemas in MongoDB, one of the most fundamental decisions developers face is whether to embed related data within a single document or reference it across multiple collections. Unlike traditional relational databases where normalization is standard, MongoDB gives you the flexibility to choose the approach that best fits your application's read and write patterns.
Understanding Embedding (Denormalization)
Embedding involves storing related data in a single document as nested fields or arrays. This approach takes full advantage of MongoDB's document model and provides excellent read performance because all related data can be retrieved in a single database query.
When to Use Embedding
- One-to-One Relationships: When two entities strongly belong together, such as a user and their user profile settings.
- One-to-Few Relationships: When an entity has a small, bounded set of related items, like a customer with a few shipping addresses.
- Data Queried Together: When the embedded data is almost always accessed along with the parent document.
- Atomic Updates: When you need atomic operations across the parent and child data without requiring multi-document transactions.
Example of an embedded schema:
{
"_id": ObjectId("60d5ecb8b3f1a23456789abc"),
"name": "Alice Smith",
"email": "alice@example.com",
"address": {
"street": "123 Innovation Way",
"city": "Tech City",
"zipCode": "94016"
}
}
Understanding Referencing (Normalization)
Referencing involves storing relationships by saving the ObjectId of a document from one collection inside a document of another collection. You then use population or aggregation stages like $lookup to join the data when needed.
When to Use Referencing
- One-to-Many (Unbounded) Relationships: When an entity can have hundreds or thousands of related items (e.g., an e-commerce product with thousands of reviews).
- Many-to-Many Relationships: When entities are shared across multiple parent documents, such as students enrolled in multiple courses.
- Frequently Updated Independent Data: When the referenced data changes frequently and is shared across documents, embedding it would cause massive write duplication.
- Avoiding the 16MB Document Limit: MongoDB enforces a strict 16MB maximum document size limit. Unbounded embedded arrays risk exceeding this limit over time.
Example of a referenced schema:
// User Document
{
"_id": ObjectId("60d5ecb8b3f1a23456789abc"),
"name": "Alice Smith"
}
// Order Document referencing the User
{
"_id": ObjectId("60d5ecd1b3f1a23456789def"),
"orderNumber": "ORD-10023",
"totalAmount": 149.99,
"userId": ObjectId("60d5ecb8b3f1a23456789abc")
}
Summary Matrix
As a rule of thumb: favor embedding by default for simplicity and speed, but switch to referencing when datasets are unbounded, heavily updated independently, or shared across multiple entities.