← Back to Databases

Key-value and document stores

Key-value and document stores are the most widely used NoSQL families. Their speed comes from designing data around how it will be read.

Key-value stores

A key-value store is essentially a giant distributed hash map: put(key, value), get(key), delete(key). Values are opaque to the database, so lookups by key are extremely fast, but you cannot query by what is inside the value. Examples include Redis, Amazon DynamoDB (which also supports richer items), Riak, and etcd for configuration.

Redis

Redis, first released by Salvatore Sanfilippo in 2009, keeps data in memory for sub-millisecond access and supports rich value types: strings, lists, sets, sorted sets, hashes, streams, and more. It is widely used for caching, session storage, rate limiting, leaderboards (with sorted sets), and message queues. Persistence options snapshot data or log every write to disk.

Caching patterns

With cache-aside, the application checks the cache, and on a miss reads the database and stores the result with a time-to-live (TTL). Write-through updates the cache whenever the database is written. Caches must be invalidated when data changes; stale caches are a classic source of bugs. Eviction policies such as least recently used make room when memory fills.

Document stores

Document databases store self-describing documents, usually JSON or a binary form such as MongoDB's BSON, grouped into collections. A document can nest objects and arrays, such as an order with its line items embedded. Queries can filter on any field, including nested ones, and secondary indexes make such queries fast. MongoDB, Couchbase, and Firestore are examples.

Embedding versus referencing

Document design asks whether related data should be embedded in one document or stored separately and referenced by ID. Embed data that is read together and owned by the parent, such as an order's line items, for single-read access. Reference data that is shared, large, or unbounded, such as a user's millions of activity events, since documents have size limits (16 MB in MongoDB) and duplicated data must be kept in sync.

Querying and aggregation

Document stores offer query languages for filtering and projecting fields, such as MongoDB's find({status: 'shipped', 'items.sku': 'A12'}). Aggregation pipelines chain stages such as $match, $group, $sort, and $lookup, which performs a join-like operation. These are powerful, but complex multi-collection queries remain more natural in SQL.

Design by access pattern

In many NoSQL systems, especially DynamoDB, schemas are designed from the queries backwards: list each access pattern, such as 'get a customer's recent orders', then choose partition keys, sort keys, and indexes so each pattern is a single efficient request. Single-table designs may store several entity types together. This is efficient but less flexible when new, unforeseen queries appear.

Worked example

A blog stored as documents: each post document contains title, body, tags as an array, and the first 20 comments embedded for fast page loads, while older comments live in a separate comments collection referencing the post's ID. Rendering a post page is one read. An index on tags makes 'all posts tagged databases' fast. Changing an author's display name, however, means updating it wherever it was copied, unless posts store only the author's ID.

Key takeaways

Key-value stores offer very fast get, put, and delete by key, with opaque values: Redis, DynamoDB, etcd. Redis (2009) keeps rich data types in memory for caching, sessions, leaderboards, and queues. Cache-aside with TTLs and careful invalidation is the common caching pattern. Document stores keep nested JSON-like documents in collections with field queries and secondary indexes: MongoDB, Couchbase, Firestore. Embed data read together and owned by the parent; reference shared or unbounded data. Aggregation pipelines transform data. Many NoSQL schemas are designed from access patterns backwards.

Flashcard

Key-value store

Distributed map from keys to opaque values

get, put, delete.

Check your understanding

In a document database, why store a user's millions of activity events in a separate collection rather than embedding them in the user document?

← Previous lesson Next lesson →