Course outline

MongoDB / Basic: document foundations / Lesson 2

Modeling embedded and referenced data

Choose document boundaries from access patterns and bounded growth. Explain embedding, references and duplication without treating flexible schema as no design.

About 4 min readContent reviewed
On this page

Lesson goals

  • Choose an aggregate boundary for atomic business updates.
  • Identify unbounded arrays and duplicated-fact ownership.

Design from operations and invariants

A document boundary should fit facts read or changed together. A shipment with a small fixed destination snapshot can embed that address, while an indefinitely growing event history usually deserves separate documents. MongoDB does not require relational joins for every shape, but references remain valid when lifecycle, reuse or growth make embedding unsuitable. List the dominant reads, writes, retention policy and consistency rules before choosing a structure. Flexible fields reduce migration friction only when their meanings and valid versions are still documented.

Embed a deliberate historical snapshot

This local document records the address used when booking 101 was accepted. It can remain unchanged if the customer later edits their current address. That is intentional historical duplication rather than a failed synchronization job. The local access prints Aqaba without consulting a customer collection. If the report instead needs the customer’s current address, name that requirement separately and use the authoritative reference. A field called address is insufficient documentation when different consumers mean historical and current facts.

javascript Illustrative mongosh; results are reasoned, not measured.
const booking = {
  _id: 101, customerId: 7,
  deliveryAddress: { city: 'Aqaba', street: 'Quay Road' },
  lines: [{ sku: 'PEN', qty: 2 }, { sku: 'PAD', qty: 1 }]
};
print(booking.deliveryAddress.city);
Expected output
Aqaba

The embedded address is the booking snapshot, while customerId can identify separately managed customer data.

Bound arrays and document size

MongoDB’s maximum BSON document size is 16 MiB for ordinary documents. An ever-growing scans array can reach that limit and also turn independent events into contention on one hot document. Keep a bounded recent summary only when its limit and update policy are clear; store complete history separately with an indexed shipment reference. Document-size limits are not performance targets: a document far below the limit may still be expensive to rewrite, transfer and cache repeatedly under a high-rate workload.

Keep history as separately queryable events

The training pattern retrieves scan events by shipmentId, ordered by event time and _id for ties. The query says nothing about whether an event is authorized merely because its reference matches: tenant scope belongs in the filter when the application model requires it. An appropriate compound index is considered later. The expected logical result is that only this shipment’s matching events appear in the specified order; exact documents require a synthetic fixture and are not invented as observed production output.

javascript Illustrative mongosh; results are reasoned, not measured.
db.getSiblingDB('quay_lab').scanEvents.find(
  { shipmentId: 101 },
  { _id: 1, occurredAt: 1, state: 1 }
).sort({ occurredAt: 1, _id: 1 }).limit(20);

A separate event collection avoids requiring the entire historical array in every shipment document read.

Name who updates duplicated facts

Duplication can serve historical snapshots or faster reads, but a copied current fact needs an owner and propagation policy. Decide whether updates are synchronous, eventually consistent or rebuilt from authoritative data. Embedding gives a single-document atomicity boundary; multiple referenced documents do not automatically update atomically together. A transaction can coordinate supported multi-document work, but it does not make an unbounded model efficient. Model invariants first, then choose transactions, an outbox or reconciliation according to the acceptable consistency delay and failure behavior.

Common errors and fixes

An events array grows without a bound

Why it happens
Historical one-to-many growth was embedded inside one parent.
How to fix it
Move full history to referenced event documents and define a bounded summary.
Prevent it next time
Estimate growth and access cost before choosing embedding.

A historical address changes after customer edits

Why it happens
A current reference was used where an immutable booking snapshot was required.
How to fix it
Store the accepted address snapshot with explicit business meaning.
Prevent it next time
Distinguish current and historical fields in the schema contract.

Copied current values disagree across documents

Why it happens
No authoritative owner or propagation/reconciliation rule was defined.
How to fix it
Choose the source of truth and implement a reviewed update policy.
Prevent it next time
Document tolerated staleness and repair evidence for every duplicate current fact.

Check your understanding

1. Should a shipment embed its latest three status summaries and its entire lifetime event history in one unbounded array?

Show worked solution

A latest-three summary can be appropriate when its bounded update rule is clear, but the complete history should not become an unlimited parent array. Store event documents with shipmentId and a useful time index. Define which representation is authoritative and how the summary is rebuilt after failure so bounded denormalization does not become unexplained inconsistency.

2. A customer changes city after placing a booking. Which city should an invoice show?

Show worked solution

Answer the business question first: an invoice usually needs the accepted billing or delivery snapshot rather than whatever current profile now contains. Store and label that snapshot deliberately. A current-contact report may legitimately follow the customer reference instead. The database model should support both meanings without pretending they are one automatically synchronized field.

Key takeaways

  • Embed bounded facts changed together; reference independent or growing histories.
  • Every duplicated current fact needs ownership and a consistency policy.

Official references