The Model
store JSON-like DOCUMENTS, nested structure included:
// collection: products
{
"_id": "p-77",
"name": "Trail Shoe",
"brand": {"name": "Ridge", "country": "us"}, // embedded!
"variants": [ // array, inline
{"sku": "ts-42-9", "size": 9, "stock": 12},
{"sku": "ts-42-10","size": 10, "stock": 3}
],
"specs": {"weight_g": 310, "waterproof": true}, // sparse fields OK
"tags": ["outdoor", "running"]
}
vs relational: variants/specs would be JOINs or child tables.
here they're PART OF THE ROW — read together, atomically.
The Core Insight: Model for Reads
document design = pre-joining what's read TOGETHER:
product page renders brand+variants+specs:
→ one fetch, zero joins, single round trip ✓
the questions that replace normalization:
- what reads together stays together (embed)
- what's queried independently gets its own collection (reference)
// reference when huge/unshared/growing-unbounded:
{
"_id": "o-1001",
"customer_id": "u-912", ← pointer, resolved separately
"items": [...] ← small, embedded — fine
}
What Document Stores Buy
| Benefit | Mechanism |
|---|---|
| Read locality | Aggregate fetched in one I/O |
| Schema flexibility | Documents vary; no migration to add a field |
| Natural dev mapping | Objects ↔ documents, impedance low |
| Atomic per-document | Update variant stock + price atomically IN the doc |
The Sharp Edges
✗ UNBOUNDED EMBEDDING
comments array growing forever → 16MB doc limits,
every read/write drags megabytes.
rule: embed BOUNDED data; extract unbounded to own collection.
✗ NO REAL JOINS (historically; modern $lookup exists but costs)
cross-entity queries = app-level fan-out or denormalized copies
with sync burden
✗ SCHEMA ANARCHY
flexibility becomes entropy without conventions:
version fields + migration discipline still needed!
✗ MULTI-DOCUMENT TRANSACTIONS
exist now but are slow/limited — designs should avoid
needing them (single-document atomicity is the sweet spot)
Indexing Still Rules Everything
documents are queried by FIELDS → indexes on those fields:
db.trips.createIndex({"rider_id": 1, "created_at": -1})
same discipline as relational: index what you filter/sort by,
compound indexes match multi-field queries,
missing indexes = collection scans over millions of docs.
"schemaless" never meant "index-free" — that misconception
causes most Mongo production incidents.
When Document Fits
✓ catalogs/products with varied nested attributes
✓ content management (articles, pages, CMS)
✓ user profiles with heterogeneous preferences
✓ event/log storage with rich payloads
✓ mobile/backend-as-a-service style APIs
reconsider when:
✗ heavy cross-entity transactions (money movement)
✗ ad-hoc analytical joins across entities
✗ relationships are THE domain (social graphs → graph DB)
Interview Framing
Document-store answers score on modeling judgment: show an embed-vs-reference DECISION with reasoning (“variants embedded — bounded and always co-read; customer referenced — queried independently”), state the unbounded-array trap unprompted, and mention indexing discipline surviving. Knowing modern transactions exist-but-cost shows current knowledge rather than decade-old folklore.
Premium Content
Unlock Document Databases and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans