How Do You Design Document Schemas in MongoDB?
Learn how to design MongoDB document schemas, when to embed versus reference data, and avoid common NoSQL modeling mistakes.
Expected Interview Answer
MongoDB document schema design means choosing, for each relationship in your data, whether to embed related data inside a single document or reference it from a separate collection, based on how the data is queried and how fast it grows.
Embedding nests related data directly inside a parent document, so a single read returns everything needed, which suits one-to-few relationships that are always read together, like an order and its line items. Referencing stores a related document's ID and requires a separate lookup (or a $lookup aggregation join), which suits one-to-many or many-to-many relationships, data that grows unbounded, or data updated independently of the parent. Getting this wrong causes either bloated documents that hit the 16MB limit and get slow to update, or excessive round trips from over-referencing. Good schema design in MongoDB is driven by query patterns first, not by normalized-table instinct.
- Embedding minimizes read round trips for tightly coupled data
- Referencing keeps documents small and independently updatable
- Schema follows query patterns, not rigid normalization rules
- Avoids hitting the 16MB document size limit from runaway embedding
AI Mentor Explanation
Think of a player's scorecard for a single match: the runs scored, balls faced, and dismissal type are embedded directly on that scorecard because you always view them together. But the player's entire career statistics across hundreds of matches are not copied onto every scorecard โ instead each scorecard just references the player's ID, and career stats are computed separately. MongoDB schema design makes this same call for every relationship: embed what is always read together and small, reference what is large or grows independently.
Step-by-Step Explanation
Step 1
Identify query patterns
List the exact reads and writes the application performs before designing any schema.
Step 2
Classify each relationship
Decide if it is one-to-few, one-to-many, or many-to-many, and whether data is bounded or unbounded.
Step 3
Choose embed or reference
Embed small, bounded, always-together data; reference large, unbounded, or independently-updated data.
Step 4
Validate against growth and size limits
Check embedded arrays cannot grow unbounded and the document stays well under the 16MB limit.
What Interviewer Expects
- Understanding that MongoDB schema design is query-driven, not normalization-driven
- Clear criteria for choosing embedding versus referencing
- Awareness of the 16MB document size limit and unbounded array growth risk
- Knowledge of $lookup as the join equivalent for referenced data
Common Mistakes
- Embedding everything because "NoSQL means no joins"
- Referencing everything and losing MongoDB's read-performance advantage
- Ignoring unbounded array growth inside an embedded document
- Not considering how often the embedded sub-data changes independently
Best Answer (HR Friendly)
โDesigning a MongoDB schema means deciding, for each piece of related data, whether to nest it inside the main document or keep it in a separate collection with a reference. I nest small, always-together data like an order's line items, and I reference large or independently growing data like a customer's full order history, so documents stay fast to read and update.โ
Code Example
// Embedded: line items always read together with the order
db.orders.insertOne({
_id: "order_1001",
customerId: "cust_55", // reference: customer grows independently
items: [
{ sku: "SKU-1", qty: 2, price: 19.99 },
{ sku: "SKU-2", qty: 1, price: 49.99 }
],
createdAt: new Date()
});
// Referenced collection: unbounded, queried independently
db.reviews.insertMany([
{ productSku: "SKU-1", rating: 5, text: "Great product" },
{ productSku: "SKU-1", rating: 4, text: "Works well" }
]);
// Joining referenced data when needed
db.orders.aggregate([
{ $match: { _id: "order_1001" } },
{ $lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customer"
}}
]);Follow-up Questions
- When would you use a hybrid approach that both embeds and references the same data?
- How does the 16MB document size limit affect schema design decisions?
- What is the bucket pattern and when does it help with unbounded arrays?
- How does $lookup performance compare to a native SQL join?
MCQ Practice
1. Which relationship is generally the best candidate for embedding in MongoDB?
Embedding suits small, bounded, one-to-few data that is always read alongside its parent document.
2. What is a key risk of embedding an unbounded array inside a document?
Unbounded embedded arrays keep growing the document, risking the 16MB limit and degrading write performance.
3. What MongoDB aggregation stage performs a join across referenced collections?
$lookup performs a left outer join between the current collection and another collection using a matching field.
Flash Cards
Embedding vs referencing? โ Embed small, bounded, always-together data; reference large, unbounded, or independently-updated data.
What limits embedding? โ The 16MB document size limit and the risk of unbounded array growth.
What is $lookup? โ The aggregation stage that joins a collection to another referenced collection, similar to a SQL join.
What drives MongoDB schema design? โ Application query patterns, not normalized-table rules.