Denormalization vs Normalization in MongoDB
MongoDB rewards denormalization; SQL rewards normalization. Here is how to choose.
Denormalization vs Normalization in MongoDB
SQL databases reward normalization (one copy of each fact, join on read). MongoDB rewards denormalization (copy data where you need it, avoid joins). Here is how to choose.
Normalization
Store each fact once. Reference other collections.
// User
{ _id: 'u1', name: 'Kunal' }
// Post
{ _id: 'p1', authorId: 'u1', title: 'Hello' }
To show a post with the author's name, populate (join) on read.
Pros:
- One copy of each fact. Update the user's name in one place.
- Smaller documents.
- No data duplication.
Cons:
- Reads require joins (populate). Extra queries.
- Slower for high-traffic reads.
Denormalization
Copy data where you need it.
// Post
{ _id: 'p1', authorId: 'u1', authorName: 'Kunal', title: 'Hello' }
To show a post with the author's name, just read the post. No join.
Pros:
- Faster reads (no join).
- Fewer queries.
- Good for high-traffic endpoints.
Cons:
- Data duplication. Update the user's name in many places.
- Risk of stale data.
- Larger documents.
When to Normalize
- Data changes often (user profile, prices).
- You need consistency (one copy of each fact).
- Reads are not high-traffic.
- The referenced document is large.
When to Denormalize
- Data rarely changes (author name on a message, category name on a post).
- Reads are high-traffic and slow with joins.
- You need fast reads for UX.
- The duplicated data is small.
Hybrid Approach
Store the ref AND a snapshot of the key fields:
{ _id: 'p1', authorId: 'u1', authorName: 'Kunal', title: 'Hello' }
Read the post without a join. When the user's name changes, update all their posts (or accept staleness for a while).
The Staleness Problem
With denormalization, the copied data can become stale. Decide:
- Update on change: when the user's name changes, update all their posts. Expensive but consistent.
- Accept staleness: the name on old posts stays as it was. Cheaper. Fine for many cases (e.g., chat messages).
The Takeaway
Normalize for data that changes often and needs consistency. Denormalize for data that rarely changes and needs fast reads. Hybrid: store the ref plus a snapshot of key fields. Decide whether to update on change or accept staleness. MongoDB rewards denormalization for high-traffic reads.
Normalization stores each fact once and references other collections (join on read). Denormalization copies data where you need it (no join). Normalize for data that changes often; denormalize for high-traffic reads of rarely-changing data.
When data rarely changes (author name on a message), reads are high-traffic and slow with joins, you need fast reads for UX, and the duplicated data is small. MongoDB rewards denormalization for high-traffic reads.
When data changes often (user profile, prices), you need consistency (one copy of each fact), reads are not high-traffic, or the referenced document is large. Use refs and populate.
Store the ref plus a snapshot of key fields. Example: { authorId: 'u1', authorName: 'Kunal' }. Read the post without a join. When the user's name changes, update all their posts (or accept staleness for a while).
Either update on change (when the user's name changes, update all their posts; expensive but consistent) or accept staleness (the name on old posts stays as it was; cheaper, fine for many cases like chat messages). Decide based on the feature's needs.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

