Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Document Databases
HLD

Document Databases

Nested objects as first-class citizens — MongoDB-style modeling, its strengths, and its sharp edges.

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

BenefitMechanism
Read localityAggregate fetched in one I/O
Schema flexibilityDocuments vary; no migration to add a field
Natural dev mappingObjects ↔ documents, impedance low
Atomic per-documentUpdate 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.

My Private Notes

Notes are auto-saved locally to this device.