Choosing an Approach
Objectives
By the end of this lesson, you should be able to:
- List the concrete trade-offs between embedding and referencing
- Choose the right approach for a given relationship, with reasoning
- Recognize that the two can be combined within a single schema
💡 Why this matters: The last two lessons covered how to embed and how to reference. This lesson covers the part that actually takes judgment, deciding which one fits a given relationship.
Side by Side
| Embedding | Referencing | |
|---|---|---|
| Query cost | One query loads everything | A second query (or populate) needed |
| Data ownership | Belongs exclusively to the parent | Can be shared or exist independently |
| Growth | Bounded, or risks the 16MB document limit | Unbounded, entirely separate documents |
| Updates | Duplicated if the same data appears elsewhere | Update once, reflected everywhere it’s referenced |
| Relational equivalent (Module 5) | Nested JSON, no real equivalent | Foreign key + JOIN |
Questions to Ask
Is the related data ever used independently of its parent? A comment (Lesson 1) never is, it only makes sense attached to its post, embed it. An author (Lesson 2) does, an author page listing all of their posts across the site needs to query authors on their own, reference them.
Could the same data need to appear in more than one place? A tag shared across hundreds of posts (Module 5’s many-to-many Tag model has the same shape here) shouldn’t be duplicated into every post that uses it, reference it. Update the tag once, every post referencing it reflects the change automatically.
Is there a hard upper bound on how much related data there could be? A handful of embedded comments is fine. An unbounded, potentially huge collection (every order a customer has ever placed) risks the document size limit, and pulls all of it along on every fetch, even when only recent orders are needed, reference it instead.
Combining Both in One Schema
Real schemas often use both at once:
const postSchema = new mongoose.Schema({
title: { type: String, required: true },
body: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, // referenced: shared, queried independently
comments: [commentSchema], // embedded: exclusive, bounded, always read together
tags: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tag' }] // referenced: shared across many posts
});
One schema, one relationship embedded, two referenced, each chosen for its own reasons, not because one approach is simply “correct” for a MongoDB schema in general.
Try It
- For each relationship in a project from this course (Module 5’s
Author/Book/Tag, or Module 9’s own examples), decide whether it should be embedded or referenced in MongoDB, and write one sentence justifying each choice. - Sketch a
Productschema withreviewsembedded andcategoryreferenced, explaining why each fits its role. - Explain, in your own words, why a heavily shared tag should almost never be embedded.
Recap
- Embedding fits data that’s exclusively owned by its parent, always read together, and reasonably bounded in size.
- Referencing fits data that’s shared, independently queried, or unbounded in size, at the cost of a second query (or
populate) to load it. - A single schema can, and often should, use both, chosen relationship by relationship, not applied uniformly across an entire application.
This is the final lesson of this module before exercises. This is also the final MongoDB-specific module in this course. Next module: the capstone, a full CRUD API backed by a real database.