SD System Design In Depth
0%
lesson system-designdatabasesdocuments

Document vs key-value stores

Module 2.2: NoSQL Architectures, Partitioning & IDs Updated Sep 17, 2026
📄 Cheat Sheet
Data Modeling in System Design Interviews w/ Meta Staff Engineer
Hello Interview Data Modeling in System Design Interviews w/ Meta Staff Engineer Watch on YouTube ↗

Contrasts modeling the same entities in relational, document and key-value stores, driven by access patterns: exactly the 'select by required operations' point of this unit.

0:00 / --:--

Concrete scenario

Sessions need lookup by token, while a catalog needs predicates on nested product attributes.

Mechanics

A minimal key-value store exposes opaque bytes by key, but products vary: Redis has server-side structured types and DynamoDB supports attributes and secondary indexes. Document stores expose fields and indexes inside records, paying parsing and index-maintenance costs.

Failure mode

Manually maintained secondary structures can diverge after a partial write. Too many document indexes amplify writes, and large documents can create contention or transfer waste.

Trade-off

Key-based access is simple and predictable; document queries improve flexibility. Select by required operations rather than assuming every key-value value is opaque or every document store provides relational constraints.

Worked example: sessions vs product catalog

Sessions: 10M active sessions, each about 1 KB, with 50k reads/s and 5k writes/s. Access is always get(token) and set(token, blob, ttl). That makes it a key-value workload. In Redis, 10M x about 1.1 KB is about 11 GB of RAM, with sub-millisecond reads and native TTL. In DynamoDB, 50k eventually consistent reads/s of items up to 4 KB cost 25k RCUs, with DynamoDB TTL for expiry. No secondary index is needed.

Catalog: 5M products with nested attributes (size, colour, specs). Queries include "category = shoes AND brand = X AND price < 100 sorted by rating". That is a document workload. MongoDB with a compound index {category: 1, brand: 1, price: 1} serves it, and partial updates with the set operator (for example setting only stock.warehouse3 to 12) avoid rewriting the whole document. Putting this in a pure KV store means building and maintaining every index yourself.

Comparison

AspectKey-value (Redis, Memcached, DynamoDB core)Document (MongoDB, Couchbase, Firestore)
LookupBy key (plus sort key in DynamoDB)By key or any indexed field, including nested fields
UpdateUsually replace the whole value (Redis types and DynamoDB UpdateExpression are exceptions)Field-level update operators (set, inc, push)
Secondary indexesNone (Redis, Memcached) or limited (DynamoDB GSI/LSI, eventually consistent GSIs)Many, including multikey (array) and text
Write costLowest: one keyGrows with the number of indexes
Latency profileVery predictableDepends on query shape and index use
Typical fitSessions, caches, carts, feature flags, idempotency keysCatalogs, CMS content, user profiles, event payloads

Modeling rules for documents

  • Embed what is read together and bounded (an order and its line items).
  • Reference what is unbounded or shared (a post's comments, a product shared by many orders).
  • Keep hot, frequently updated fields (view counters) out of large documents, or in a separate KV counter.

Failure modes

  • GSI lag in DynamoDB: a read from a global secondary index right after a write may not see it.
  • Index explosion: 15 indexes on a document collection can make each insert cost 16 B-tree updates.
  • Hot documents: a single "global counters" document serializes all writers on one lock.
Check yourself Question 1 of 3
Cost of field awareness recall
From: Mechanics

A document store can filter and index on fields inside a record, while a minimal key-value store treats the value as opaque bytes. What does the document store pay for that capability?

Key Takeaways

Key-value products differ: some expose opaque bytes and others structured values or indexes.
Document indexes improve field queries while amplifying writes.
Select from required operations and guarantees rather than category labels.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue