6.1 Embedding vs. Referencing Tradeoffs

Key Takeaways

  • The foundational axiom of MongoDB data modeling is: 'Data that is accessed together should be stored together.'
  • Embedding (denormalization) stores subdocuments or arrays inside a single document, providing atomic writes, zero-join reads, and cache locality up to the 16 MB BSON limit.
  • Referencing (normalization) stores entities in separate collections linked by ID references, eliminating duplication and accommodating 1:many, 1:infinite, and many:many relationships.
  • Cardinality dictates strategy: 1:1 and 1:few favor embedding, while 1:many (large) and 1:infinite require referencing to prevent exceeding the 16 MB document cap.
  • Parent Referencing (storing parent ID in each child) scales infinitely without parent document growth, whereas Child Referencing risks the unbounded array anti-pattern.
Last updated: September 2026

6.1 Embedding vs. Referencing Tradeoffs

In relational database management systems (RDBMS), data modeling centers on normalization (specifically Third Normal Form or 3NF). Entities are separated into distinct tables to eliminate data redundancy, and relationships are re-established at query time using SQL JOIN operations. In contrast, MongoDB is designed around the document model, where data modeling is governed by application access patterns rather than abstract mathematical normalization rules.

The foundational design rule of MongoDB schema design is:

"Data that is accessed together should be stored together."

When designing schemas in MongoDB, developers face two fundamental modeling approaches for representing relationships between entities:

  1. Embedding (Denormalization): Nesting related data as embedded subdocuments or arrays within a single top-level BSON document.
  2. Referencing (Normalization): Storing related entities in separate documents across one or more collections and linking them via unique identifiers (typically BSON ObjectId references).
+-----------------------------------------------------------------------------+
|                        MongoDB Data Modeling Models                         |
|                                                                             |
|  +-------------------------------------+  +------------------------------+  |
|  |      EMBEDDING (Denormalization)    |  |  REFERENCING (Normalization) |  |
|  |                                     |  |                              |  |
|  | {                                   |  | // Collection: users         |  |
|  |   _id: ObjectId("..."),             |  | { _id: ObjectId("u1"),       |  |
|  |   name: "Alice Smith",              |  |   name: "Alice Smith" }      |  |
|  |   addresses: [                      |  |                              |  |
|  |     { city: "Seattle", zip: "98101" }|  | // Collection: addresses     |  |
|  |   ]                                 |  | { _id: ObjectId("a1"),       |  |
|  | }                                   |  |   userId: ObjectId("u1"),     |  |
|  |                                     |  |   city: "Seattle" }          |  |
|  | - Single document read              |  | - Multiple queries / $lookup |  |
|  | - Atomic updates                    |  | - Independent lifecycles     |  |
|  | - 16 MB limit constraint            |  | - Scalable unbounded growth  |  |
|  +-------------------------------------+  +------------------------------+  |
+-----------------------------------------------------------------------------+

Understanding when to embed, when to reference, and how to evaluate cardinality and access patterns is a central pillar of the MongoDB Associate Developer Exam.


1. Embedding (Denormalization)

Embedding incorporates child entities directly within the parent document as nested key-value objects or arrays of subdocuments.

Advantages of Embedding

  1. High-Performance Single-Document Reads: Retrieving a document loads all associated child entities in a single disk I/O operation and a single network round-trip. There is no need for secondary lookups or joins.
  2. Single-Document ACID Atomicity: MongoDB guarantees that write operations (inserts, updates, deletes) on a single document are strictly atomic, even when modifying nested arrays and subdocuments. Complex updates to parent and child data succeed or fail as a single unit without requiring multi-document distributed transactions.
  3. Optimized Cache Locality in WiredTiger: Because related data is contiguous within the BSON payload, the WiredTiger storage engine caches the entire entity in RAM, minimizing cache misses and memory paging.

Risks and Limitations of Embedding

  1. The 16 MB BSON Document Limit (BSONObjMaxUserSize): MongoDB enforces a hard maximum size limit of 16 Megabytes (16,777,216 bytes) per BSON document. If an embedded array grows continuously over time (such as accumulating log messages, click events, or user comments), the document will eventually exceed 16 MB and throw a BSONObjectTooLarge write error.
  2. Data Duplication & Update Anomalies: If embedded data is shared across multiple parent documents (e.g., embedding full vendor details in every product document), updating a vendor's phone number requires updating thousands of documents across the collection rather than a single record, risking data inconsistency.
  3. Memory and Bandwidth Overhead: If an application frequently queries the parent document but only needs a small subset of fields (e.g., retrieving user authentication credentials), loading massive embedded arrays consumes excessive RAM and network bandwidth.

Example: Bounded 1:Few Embedding

// Bounded 1:Few relationship: A user with billing and shipping addresses
db.users.insertOne({
  _id: ObjectId("66d5a100f1e8a93b4c5d6e10"),
  username: "developer_dan",
  email: "dan@example.com",
  status: "ACTIVE",
  addresses: [
    {
      type: "BILLING",
      street: "100 Technology Way",
      city: "San Jose",
      state: "CA",
      postal_code: "95110",
      is_default: true
    },
    {
      type: "SHIPPING",
      street: "456 Distribution Blvd",
      city: "Reno",
      state: "NV",
      postal_code: "89501",
      is_default: false
    }
  ],
  preferences: {
    newsletter: false,
    theme: "dark",
    currency: "USD"
  }
});

In this example, an individual user will rarely have more than 3 to 5 addresses. Because the cardinality is strictly bounded, embedding guarantees that loading the user profile retrieves all contact details instantaneously with zero joins.


2. Referencing (Normalization)

Referencing maintains distinct collections for different entities and establishes relationships by storing the _id of one document inside another document.

Advantages of Referencing

  1. Zero Risk of Hitting the 16 MB Limit: Child entities are stored as independent documents in their own collection. A parent can have millions of associated children without increasing the physical byte size of the parent document.
  2. Elimination of Data Redundancy: Shared entities (such as manufacturers, categories, or authors) exist in exactly one location. Updating the referenced entity immediately reflects across the entire system without batch update operations.
  3. Independent Querying and Indexing: Child documents can be queried, filtered, sorted, paginated, and indexed independently without loading parent documents into working memory.

Disadvantages of Referencing

  1. Multiple Network Round-Trips or Server Joins: Retrieving related entities requires either multiple application queries or a $lookup aggregation pipeline stage, increasing CPU utilization and query execution time.
  2. Cross-Collection Atomicity Overhead: Mutating both the parent and referenced documents simultaneously requires explicit multi-document ACID transactions (session.startTransaction()), which introduces coordination locks and replication overhead.

Example: E-Commerce Order with Referencing

// 1. Customers Collection
db.customers.insertOne({
  _id: ObjectId("66d5a200f1e8a93b4c5d6e20"),
  company_name: "Acme Logistics Corp",
  tax_id: "XX-XXXXXXX",
  credit_limit: NumberDecimal("50000.00")
});

// 2. Orders Collection (Referencing customer by ObjectId)
db.orders.insertOne({
  _id: ObjectId("66d5a200f1e8a93b4c5d6e21"),
  order_number: "ORD-2026-90412",
  customer_id: ObjectId("66d5a200f1e8a93b4c5d6e20"), // Reference to customers._id
  order_date: ISODate("2026-09-02T14:30:00Z"),
  status: "CONFIRMED",
  total_amount: NumberDecimal("14250.00"),
  item_count: 3
});

// 3. Joining data on read using $lookup aggregation stage
db.orders.aggregate([
  { $match: { order_number: "ORD-2026-90412" } },
  {
    $lookup: {
      from: "customers",
      localField: "customer_id",
      foreignField: "_id",
      as: "customer_details"
    }
  },
  { $unwind: "$customer_details" }
]);

3. Relationship Cardinality & Modeling Taxonomy

Cardinality describes the numerical relationship between two entities. Evaluating cardinality is the most reliable method for choosing between embedding and referencing.

Cardinality TypeNumerical ScaleRecommended PatternModeling MechanismTypical Example
One-to-One (1:1)Exactly 1 to 1EmbeddingSubdocument in parentUser profile inside users
One-to-Few (1:N bounded)1 to 2–10EmbeddingArray of subdocumentsPerson's phone_numbers or addresses
One-to-Many (1:N large)1 to 100s–1,000sReferencingChild or Parent ReferenceCompany employees or Product parts
One-to-Squillions / Infinite (1:∞)1 to millions+ (unbounded)Parent ReferencingParent ID stored in childIoT sensor_readings or Server access_logs
Many-to-Many (N:M)Many to ManyReferencingTwo-Way Referencing / Join collectionStudents and courses, Books and authors
+-----------------------------------------------------------------------------+
|                        Referencing Strategies Matrix                        |
|                                                                             |
|  1. CHILD REFERENCING (1:Many Bounded)                                      |
|     Parent: { _id: 1, name: "Engineering", emp_ids: [101, 102, 103] }      |
|     Risk: Array in parent grows with every child added.                     |
|                                                                             |
|  2. PARENT REFERENCING (1:Many Large / 1:Infinite)                          |
|     Child:  { _id: 101, name: "Alice", dept_id: 1 }                         |
|     Scale: Infinitely scalable; parent document size never changes.         |
|                                                                             |
|  3. TWO-WAY REFERENCING (Many-to-Many N:M)                                  |
|     Student: { _id: "s1", name: "Alex", course_ids: ["CS101", "DB301"] }     |
|     Course:  { _id: "CS101", title: "Algorithms", student_ids: ["s1", "s2"] }|
+-----------------------------------------------------------------------------+

The Three Referencing Strategies

Strategy A: Child Referencing (Parent stores Array of Child IDs)

  • The parent document contains an array of ObjectId values pointing to children: { _id: 1, name: "Project X", task_ids: [ ObjectId("t1"), ObjectId("t2") ] }.
  • When to use: When the number of children is bounded and small (e.g., fewer than 100 items), and the parent needs to preserve child ordering.
  • Danger: If the child array is unbounded, the parent document will continuously grow, risking index degradation and the 16 MB limit.

Strategy B: Parent Referencing (Child stores Parent ID)

  • Each child document holds a scalar field referencing the parent's _id: { _id: ObjectId("log_99"), server_id: "srv_east_01", message: "Disk OK", timestamp: ISODate() }.
  • When to use: 1:Many large and 1:Infinite relationships (logs, clicks, sensor feeds, audit trails). Adding new children requires only inserting a new child document; the parent document is never modified.

Strategy C: Two-Way Referencing (Bidirectional References)

  • Both documents store arrays of each other's IDs. Useful in Many-to-Many relationships where queries frequently navigate from both directions (e.g., finding all courses for a student, and finding all students in a course).

4. Comprehensive Architectural Comparison

Technical MetricEmbedding (Denormalization)Referencing (Normalization)
Query Read PerformanceOptimal (1 read operation, contiguous storage)Lower (Requires $lookup or secondary queries)
Write PerformanceHigh (Atomic in-place modification)Varies (May require multi-collection writes)
Atomicity & ConsistencyBuilt-in single-doc ACID (No transaction overhead)Requires Multi-Document Transactions for multi-doc ACID
Document Size RiskHigh risk of hitting 16 MB limit if array is unboundedZero risk; child documents scale independently
Data DuplicationHigh if denormalizing shared entitiesNone (Single source of truth)
Memory (Working Set)May load unneeded child fields into RAMLoads only requested collections into RAM
Index OverheadMulti-key indexes on arrays can become largeStandard single-field indexes on _id and foreign keys

5. Exam Traps & Anti-Patterns

Exam Trap 1: The Unbounded Array Anti-Pattern An e-commerce platform models product reviews by embedding a reviews array directly inside the products document. Over time, popular products accumulate 50,000 reviews. This design violates MongoDB best practices because:

  1. The document risks exceeding the 16 MB limit.
  2. Pushing new reviews ($push) causes document growth, forcing WiredTiger to reallocate storage pages on disk and degrading write throughput.
  3. Fetching product catalog listings inadvertently transfers megabytes of review data over the network. Correct Solution: Store reviews in a separate reviews collection using Parent Referencing ({ _id: ..., product_id: ..., rating: 5, comment: "..." }) or the Subset Pattern.

Exam Trap 2: Defaulting to Relational 3NF in MongoDB Splitting a simple 1:1 user profile or a bounded 1:3 address list into separate collections linked by foreign keys introduces unnecessary $lookup joins, destroys single-document atomicity, and degrades performance. In MongoDB, bounded 1:1 and 1:few relationships should always be embedded unless strict data isolation or independent security ACLs are required.

Loading diagram...
Embedding vs Referencing Decision Tree
Test Your Knowledge

An IoT application collects temperature readings from 10,000 industrial sensors every five seconds. A junior engineer proposes storing all sensor readings in an embedded array named 'readings' inside each sensor's document. Why is this proposed schema flawed?

A
B
C
D
Test Your Knowledge

A user management service stores user accounts, where each user has between one and three delivery addresses. Addresses are always displayed alongside the user profile and are never queried independently. Which schema design strategy is most appropriate?

A
B
C
D
Test Your Knowledge

What is the primary operational advantage of Parent Referencing over Child Referencing in a 1:Many relationship with thousands of child documents?

A
B
C
D
Test Your Knowledge

Under what condition is Referencing (Normalization) strictly preferred over Embedding for a One-to-One (1:1) relationship in MongoDB?

A
B
C
D