9 min read
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
System Design Index
Start Here
Tier 1 -- Building Blocks
Scale Reads
Scale Writes
Database Selection
Traffic Control
Consistency & Coordination
Estimation
Tier 2 -- Core Systems
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
Document Store (MongoDB, DynamoDB)
1. What Is It?
A document store is a NoSQL database that stores data as semi-structured documents — typically JSON, BSON, or XML — rather than rows in fixed-schema tables. Each document is a self-contained unit that can hold nested objects, arrays, and mixed types. The schema is flexible: two documents in the same "collection" (MongoDB) or "table" (DynamoDB) can have entirely different fields.
Without document stores, teams that need flexible or evolving schemas are forced into painful SQL migrations every time the data model changes, or into denormalized "schemaless" hacks like storing JSON blobs in VARCHAR columns. Document stores solve this natively: add a new field to one document, and no migration is required. They also shine for hierarchical data (e.g., a user profile with embedded addresses, preferences, and tags) where SQL would require 4-5 JOINs to reconstruct what a single document fetch returns instantly.
A backend team is building a product catalog where different product categories (electronics, clothing, furniture) each require different sets of attributes. New product types are added frequently, and each addition currently triggers a painful schema migration on their SQL database. Which characteristic of document stores most directly addresses this pain point?
2. How It Works
Core Mechanism
A document store maps a document ID () to a document (a rich, nested data structure). Internally, documents are grouped into collections (MongoDB) or tables (DynamoDB). Unlike relational databases, there's no enforced schema — the database stores whatever fields the application provides.
Write Path:
- Application sends a document (
INSERT/PutItem) - The storage engine serializes and writes it to disk (WiredTiger in MongoDB; a distributed SSTable-like store in DynamoDB)
- For : MongoDB writes to the (journal) before acknowledging; DynamoDB replicates to 3 AZs before acknowledging
- Secondary indexes are updated asynchronously (DynamoDB GSIs) or synchronously (MongoDB)
Read Path:
- Application queries by
_id/ partition key → O(1) lookup via a , or O(log n) via a - Or queries by non-primary fields → full collection scan unless a exists
- For embedded arrays and nested fields, the query engine filters in-memory after fetching candidate documents
Document Store: Read by Primary Key
Application
│
▼ GET /users/u123
Query Engine
│
▼ Hash(_id) → Shard/Partition
Storage Node
│
▼ B-tree lookup → Page cache (RAM) or Disk
Returns document (single round-trip, no JOIN)
Mermaid: Architecture Diagram
Data Model Example
MongoDB — User Profile Document:
{ "_id": "u_7f3a91c", "username": "alice", "email": "alice@example.com", "addresses": [ { "type": "home", "city": "San Francisco", "zip": "94105" }, { "type": "work", "city": "Oakland", "zip": "94612" } ], "preferences": { "notifications": true, "theme": "dark" }, "tags": ["premium", "beta-tester"], "created_at": "2024-01-15T08:30:00Z" }
DynamoDB — E-commerce Order:
{ "PK": "USER#u_7f3a91c", "SK": "ORDER#2024-01-15#ord_abc123", "status": "shipped", "items": [ { "sku": "PROD-42", "qty": 2, "price_cents": 1999 } ], "total_cents": 3998, "shipping_address": { "city": "San Francisco", "zip": "94105" } }
A backend engineer notices that a query filtering users by their email field on a document store collection is running very slowly as the collection grows to millions of documents. The collection is queried by _id for most operations, but this email lookup is increasingly common. What is the most likely reason for the slow query, and what is the appropriate fix?
3. Variants & Comparisons
Document Store Flavors
| Approach | How It Works | Pros | Cons | Best For |
|---|---|---|---|---|
| MongoDB | BSON documents, WiredTiger storage engine, native sharding via mongos router | Rich query language (aggregation pipeline), multi-document ACID (v4.0+), flexible secondary indexes | Self-managed sharding complexity, 16 MB doc limit | General-purpose apps, content management, catalogs |
| DynamoDB | Managed AWS service, partition key + sort key model, SSTable-based storage | Serverless/fully managed, single-digit ms latency, auto-scaling, Global Tables | Limited query patterns (must design around access patterns upfront), 400 KB item limit, vendor lock-in | High-scale, low-ops microservices; serverless; multi-region |
| Couchbase | JSON documents + built-in caching (Memcached-compatible), N1QL SQL-like query language | Very low latency (data lives in RAM), familiar SQL syntax | More complex ops than DynamoDB, niche adoption | Mobile sync, low-latency reads, hybrid SQL/NoSQL |
| Firestore | Managed Google Cloud document store, real-time sync via WebSocket | Real-time listeners, tight Firebase integration, offline SDK | Limited query flexibility, Google Cloud lock-in | Mobile/web apps needing real-time sync |
| Amazon DocumentDB | MongoDB-compatible API on Aurora-based storage | Managed MongoDB alternative on AWS | Not true MongoDB (some API incompatibilities), slower on write-heavy loads | Teams wanting managed MongoDB without ops burden |
MongoDB vs. DynamoDB Head-to-Head
| Dimension | MongoDB | DynamoDB |
|---|---|---|
| Schema | Flexible BSON | Flexible JSON, but key schema is fixed |
| Query Flexibility | High — any field, aggregation pipeline, full-text | Low — must query via partition key or GSI |
| ACID Transactions | Multi-document, multi-collection (v4.0+) | Single-item atomic; limited multi-item transactions (TransactWrite, ≤25 items) |
| Latency | 1–10 ms (depends on index, RAM) | Single-digit ms (SLA), measured server-side |
| Scalability | Manual sharding setup required | Automatic, transparent |
| Ops Overhead | Medium-High (self-managed) or Atlas (managed) | Zero (fully managed) |
| Cost Model | Per-instance/hour | Per read/write capacity unit (or on-demand) |
| Max Document/Item Size | 16 MB | 400 KB |
| Consistency | Tunable (primary reads = strong; secondary = eventual) | Eventually consistent by default; opt-in strong consistency (2x RCU) |
A startup is building a serverless e-commerce platform on AWS that expects unpredictable traffic spikes, needs single-digit millisecond read latency under load, and wants zero database operations overhead. However, the team is concerned because their access patterns are not fully defined yet and may require querying items by several different attributes over time. Which trade-off should they be most aware of when choosing DynamoDB for this use case?
4. When to Use It (and When NOT To)
Use Document Stores When:
- Flexible or evolving schema: Products/catalogs where different items have different attributes (shoes have sizes, books have ISBNs). Schema changes are frequent during development.
- Hierarchical/nested data: User profiles with embedded addresses, preferences, and metadata — data that belongs together should be stored together (avoid JOIN overhead).
- Read-heavy workloads with (storing related data together in one document, even if it means duplicating some data, to avoid expensive JOINs): You can pre-embed related data and fetch it in a single read. At ~50K+ QPS read, avoiding JOINs matters.
- Horizontal write scale needed: At 10K+ writes/sec sustained, sharded document stores outperform single-node SQL. MongoDB or DynamoDB auto-scaling handle this natively.
- Unpredictable or bursty traffic (DynamoDB on-demand mode): Pay per request, no .
Do NOT Use Document Stores When:
- Complex multi-entity JOINs are frequent: If your queries routinely JOIN 3+ entities with arbitrary filter combinations (e.g., ad-hoc analytics), SQL wins. Document stores punish you for querying non-indexed fields.
- across entities is required: Financial transactions (debit account A, credit account B) need distributed ACID. MongoDB 4.0+ supports this, but at performance cost; DynamoDB TransactWrite is limited to 25 items. Prefer PostgreSQL or CockroachDB.
- You don't know your access patterns yet (DynamoDB specifically): DynamoDB requires upfront schema design around access patterns. If requirements are volatile, MongoDB or SQL is more forgiving.
- Document size exceeds limits: MongoDB 16 MB cap / DynamoDB 400 KB cap. Large binary blobs belong in object storage (S3), not documents.
Decision Triggers
| Constraint | Reach For |
|---|---|
| Schema changes frequently, team moves fast | MongoDB (flexible, rich queries) |
| Fully managed, auto-scale, AWS ecosystem | DynamoDB |
| Need complex aggregations + schema flexibility | MongoDB Atlas |
| <10 ms P99, serverless, predictable access patterns | DynamoDB |
| Need strong consistency across multiple documents | MongoDB (with transactions) or NewSQL |
| Hierarchical data, catalog items with variable fields | Any document store |
Your team is building a fintech application that transfers funds between user accounts. The core operation debits one account and credits another atomically — both must succeed or neither should. You're evaluating whether to use a document store (like DynamoDB) or a relational database (like PostgreSQL). Which consideration most strongly argues against using a document store here?
5. Real-World Usage
Foursquare → MongoDB
Foursquare stores venue and check-in data in MongoDB. Their venue documents naturally embed tags, categories, and tips — data that would require multiple SQL tables. At peak they handled millions of check-ins with MongoDB's horizontal . The key insight: venue data is read far more than written, and embedding related data eliminates JOIN .
Samsung → DynamoDB
Samsung uses DynamoDB as the metadata index for petabytes of mobile app backups (voice recordings, notes, contacts stored in S3). The key metrics: low- key-value lookups, automatic scaling for unpredictable traffic from hundreds of millions of devices, and no ops burden. Samsung achieved 30%+ cost reduction by migrating cold data to DynamoDB Standard-IA tables.
Lyft → DynamoDB
Lyft runs 100+ microservices on DynamoDB, including GPS coordinate storage for all rides. The ride-tracking use case is a perfect fit: writes are key-based (ride ID), scale is enormous and bursty, and the simple access pattern (get ride by ID) aligns with DynamoDB's partition-key model. DynamoDB's single-digit ms latency supports real-time driver location updates.
A social app stores venue profiles where each venue has associated tags, categories, and user tips. The data is read frequently but rarely updated. Which database design choice best justifies using a document store over a relational database for this use case?
6. Interview Cheat Sheet
5 Sentences to Show Deep Understanding
-
"Document stores trade query flexibility for horizontal scalability — by embedding related data in a single document, you eliminate JOINs and can shard by document ID, but you lose the ability to query arbitrarily across entities without secondary indexes."
-
"The key design decision with DynamoDB is access-pattern-first modeling: because it can only query efficiently by partition key or GSI, you must define your access patterns before designing the schema — the opposite of SQL's query-anything model."
-
"MongoDB added multi-document ACID transactions in v4.0, but they come at a performance cost — they're a tool for correctness on critical paths, not a replacement for careful in the hot path."
-
"At scale, document stores shine for write-heavy workloads by on a high-cardinality key (user ID, order ID) — but hot partitions are the enemy: a celebrity user generating 100x traffic needs composite shard keys or read replicas."
-
"DynamoDB's single-digit ms claim is measured server-side — real end-to-end P99 includes network , SDK overhead, and potential throttling if RCU/WCU limits are hit."
Common Follow-Up Questions
Q: When would you choose MongoDB over DynamoDB? A: When you need rich ad-hoc querying (aggregation pipeline, full-text search), schema flexibility during development, or multi-document ACID transactions. DynamoDB wins when you need zero ops, auto-scaling, and have well-defined access patterns.
Q: How do you handle a many-to-many relationship in a document store? A: Two approaches: (1) embed IDs of related entities and resolve them at application layer (2 queries); (2) use a reference pattern where a separate "join document" stores the relationship. For DynamoDB, the single-table design pattern handles this with overloaded partition/sort keys.
Q: What's the problem with DynamoDB and how do you solve it? A: A sudden spike of reads/writes to one partition key exhausts that partition's . Solutions: (1) add a random suffix to spread hot keys across partitions; (2) use DAX (DynamoDB Accelerator) as a for hot reads; (3) use on-demand mode to absorb spikes.
Q: How does MongoDB ensure ?
A: Write-Ahead Log (journal) + replica set. MongoDB writes to the WiredTiger journal before acknowledging a write (with j:true). The replica set (3 nodes) ensures if the primary fails — elections happen in <10s via Raft-like .
Connections to Other Building Blocks
- Caching (Redis): Document stores are often paired with Redis as a look-aside cache. MongoDB reads can be slow on cold data; cache hot documents by ID.
- : Both MongoDB and DynamoDB shard by partition key. Choosing a high-cardinality, uniform-distribution shard key prevents hot partitions (see Sharding & building block).
- Message Queues: DynamoDB Streams (change data capture) can trigger /SQS workflows — useful for patterns where document writes fan out to downstream services.
- Search Engine (Elasticsearch): Document stores lack full-text search. A common pattern: write to MongoDB/DynamoDB as the source of truth, stream changes to Elasticsearch for search queries.
- Wide-Column Stores: DynamoDB's data model is closer to wide-column (Cassandra) than to true document stores — partition key + sort key + sparse attributes. The difference is query flexibility: DynamoDB allows nested JSON values; Cassandra does not.
Glossary History
Click dotted jargon to save explanations here.
Glossary History
Click dotted jargon to save explanations here.