Embedding vs Referencing in MongoDB: Key Differences and Usage
embedding stores related data within the same document, making reads faster and simpler. Referencing stores related data in separate documents linked by IDs, which keeps data normalized and is better for large or frequently changing data.Quick Comparison
This table summarizes the main differences between embedding and referencing in MongoDB.
| Factor | Embedding | Referencing |
|---|---|---|
| Data Storage | Related data stored inside one document | Related data stored in separate documents with references |
| Read Performance | Faster reads as all data is in one place | Slower reads due to additional queries or lookups |
| Data Duplication | Possible duplication if embedded in many documents | No duplication, data is normalized |
| Data Size Limit | Limited by MongoDB document size (16MB) | No size limit as data is split |
| Update Complexity | Updates simpler for embedded data | Updates require multiple operations |
| Use Case | Good for tightly related data and fast reads | Good for large, complex, or frequently changing data |
Key Differences
Embedding means putting related data inside the same MongoDB document. This makes reading data very fast because you get everything in one go without extra queries. However, embedding can cause duplication if the same data is repeated in many documents, and you must keep the document size under 16MB.
Referencing means storing related data in separate documents and linking them using unique IDs. This keeps data normalized and avoids duplication. But reading data requires extra queries or using $lookup to join data, which can slow down performance. Referencing is better when data changes often or is very large.
Choosing between embedding and referencing depends on your application's needs for speed, data size, and how often data changes.
Code Comparison
Here is an example of embedding related data inside a single document in MongoDB.
db.users.insertOne({
_id: 1,
name: "Alice",
address: {
street: "123 Maple St",
city: "Springfield",
zip: "12345"
}
})
// Query to find user with embedded address
db.users.findOne({_id: 1})Referencing Equivalent
Here is how referencing stores related data in separate documents linked by IDs.
db.users.insertOne({
_id: 1,
name: "Alice",
address_id: 101
})
db.addresses.insertOne({
_id: 101,
street: "123 Maple St",
city: "Springfield",
zip: "12345"
})
// Query to find user and then address
const user = db.users.findOne({_id: 1});
const address = db.addresses.findOne({_id: user.address_id});
// Or use aggregation with $lookup
db.users.aggregate([
{
$match: { _id: 1 }
},
{
$lookup: {
from: "addresses",
localField: "address_id",
foreignField: "_id",
as: "address"
}
}
])When to Use Which
Choose embedding when your related data is small, tightly connected, and you want fast reads without extra queries. Examples include user profiles with addresses or product details.
Choose referencing when your related data is large, shared across many documents, or changes frequently. This avoids duplication and keeps updates simpler. Examples include orders referencing customers or posts referencing authors.