Embedding vs referencing

MongoDB · Practical · 14 min

Schema design is the single biggest factor in MongoDB performance and simplicity.

The guiding rule is data that is accessed together should be stored together. Design from the queries your app runs, not from an entity diagram.

Embed child data inside the parent when it is read with the parent, belongs to one parent and is bounded in size: addresses in a user, line items in an order, the last few reviews on a product. One read fetches everything and a single-document write updates it atomically.

Reference (store an _id and look it up) when:

  • the related data is large or grows without bound (all of a user's events),
  • it is shared by many parents and updated independently (an author shown on many books),
  • it is often queried on its own.

For one-to-many, you can reference from the child (order.customerId) or keep an array of ids in the parent when it's small. Many-to-many is usually arrays of ids on one or both sides.

Duplication is acceptable when it saves reads: storing the product name in each order line freezes it at purchase time, which is actually correct. The cost is updating copies when they must change.

Common patterns have names: subset (embed the 10 newest reviews, keep the rest in their own collection), extended reference (copy a few fields of the referenced document), bucket (group time-series points per hour), computed (store running totals).

Example

// Embedded: one read renders the order page, one atomic write updates it
{ _id: 9001, customerId: 42, status: "paid",
  shipTo: { city: "Yerevan", street: "Abovyan 1" },
  items: [ { sku: "PEN-01", name: "Pen", qty: 3, price: 1.5 } ] }

// Referenced + extended reference: customers live in their own collection,
// the order copies only the name it needs to display
{ _id: 9002, customer: { _id: 42, name: "Ana" }, items: [ ... ] }

// Subset pattern: product keeps its 3 newest reviews, all reviews elsewhere
{ _id: "PEN-01", name: "Pen", reviewCount: 812,
  recentReviews: [ { by: "ben", stars: 5 }, { by: "cy", stars: 4 }, { by: "di", stars: 5 } ] }

Remember

  • Model for access patterns: what is read together lives together
  • Embed bounded, owned data; reference large, shared or unbounded data
  • Controlled duplication trades write effort for fewer reads
  • Know the named patterns: subset, extended reference, bucket, computed

Watch out for

  • Porting a normalized relational schema one table per collection and then joining everything with $lookup.
  • Embedding an array that grows forever, like every chat message in a room document.

Check yourself

  1. A blog post has thousands of comments, but the post page shows only the latest 5. Which design fits best?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.mongodb.com/docs/manual/data-modeling/