Document databases
Records stored as JSON documents that the database can query, index and update field by field.
3 technologies on this page ↓How it works
A document database stores each record as a self-contained document, usually JSON or a binary form of it such as MongoDB’s BSON, grouped into collections. Like a key-value store it can fetch a document by its ID, but it also understands what’s inside. You can filter on any field, including nested objects and arrays, index those fields, change one field without rewriting the rest, and run aggregations. Documents in one collection don’t need the same fields, so the shape can change without a migration, and most databases can still validate documents against a schema if you want one. Data that’s read together, such as an order and its line items, usually lives in one document, so reading it is one lookup, but data shared between documents gets copied or linked by ID, and joins across collections are limited. To scale out, a collection is split across shards by a shard key: a query that includes the key goes to one shard, and one that doesn’t goes to all of them.
A filing cabinet of complete forms, one folder per customer. The clerk can pull every folder where the city is Oslo, and new forms can gain boxes without reprinting the old ones.
Reach for it when
- Records with nested, varying fields: product catalogs, user profiles, content
- Data that’s read and written as one object, like an order with its line items
- Apps whose data shape changes often, especially when the code already works in JSON
Think twice when
- Data with many relationships, queried from every side; joins across collections are limited
- Work that needs transactions across many records all the time; they exist, but cost more than single-document writes
A real example
An online shop keeps each product as one MongoDB document: name, price, a specs object whose fields differ between laptops and shoes, and an array of sizes with stock counts. An index on specs.brand serves the brand filter, and a price change is one $set on one field. A monthly report joining products with orders and returns, though, is easier in SQL.
Technologies
Specific products, and what each does differently.
Amazon DynamoDBAWSAWS’s serverless key-value and document database, with single-digit-millisecond reads at any size.Mainly Key-value stores| Commercial product | MongoDB, Inc. | SSPL v1 (Community Server) | 2026-10-05 | |
Amazon DynamoDB | Managed service on AWS | Amazon Web Services | Proprietary | 2026-10-05 |
| Commercial product | Arango (ArangoDB Inc.) | Business Source License 1.1 since 3.12 (2024), each release converting to Apache 2.0 after four years; the prebuilt Community Edition is under the ArangoDB Community License (internal business use, datasets under 100 GB); Apache 2.0 before 3.12 | 2026-10-06 |
What each provider calls it
- AWS
- Amazon DocumentDB (MongoDB-compatible); DynamoDB also stores JSON documents
- Google Cloud
- Firestore
- Azure
- Azure Cosmos DB, with its own NoSQL API or a MongoDB-compatible one
- Open source & others
- MongoDB (SSPL, source-available), Apache CouchDB, FerretDB (MongoDB-compatible, on PostgreSQL), ArangoDB (BSL, also a graph database); PostgreSQL’s `jsonb` for documents inside a relational database
See it in a real stack
Architectures that use document databases
In code · python
from pymongo import MongoClient
products = MongoClient()["shop"]["products"]
products.insert_one({
"_id": "sku-17", "name": "Trail runner", "price": 89,
"specs": {"brand": "Ostra", "drop_mm": 6},
"sizes": [{"eu": 42, "stock": 3}, {"eu": 43, "stock": 0}],
})
products.create_index("specs.brand") # index a nested field
cheap = products.find({"specs.brand": "Ostra", "price": {"$lt": 100}})
products.update_one({"_id": "sku-17"}, {"$set": {"price": 79}}) # change one fieldWorth exploring
Often confused with
Where it came from2005–2019
By the mid-2000s, web applications passed data around as JSON, which Douglas Crockford described in RFC 4627 in 2006, while relational databases made developers split every object into rows across tables and join them back together. In April 2005 Damien Katz, who had worked on Lotus Notes at IBM, started CouchDB: a database of JSON documents with a schema-free design, read and written over HTTP. It became a top-level Apache project in November 2008.
MongoDB, built at 10gen, had its first official release in February 2009. It kept the JSON-like documents but added what developers expected from a database, such as queries on any field, secondary indexes and in-place updates. Later releases filled in what the early versions left out, including the WiredTiger storage engine, acquired in 2014, and multi-document ACID transactions in 2018.
The model then spread beyond MongoDB itself. In October 2018 MongoDB moved to the SSPL, aimed at companies offering it as a service, and in January 2019 AWS launched DocumentDB, its own MongoDB-compatible service. Relational databases met documents halfway: PostgreSQL 9.4 added the indexable jsonb type in 2014. Today the same JSON record can live in a document database, a relational one or DynamoDB.
Why it’s built this way
- Store objects whole, as JSON
- Applications already worked with nested objects. Keeping an object and its parts in one document removed the mapping to tables and made reading it a single lookup.
- No fixed schema per collection
- Each document can have its own fields, so a new field ships with the code instead of waiting for a migration. Optional schema validation lets teams add the guarantees back where they want them.
- Shard by a key the developer chooses
- Splitting a collection across servers by a shard key lets the cluster grow, and queries that name the key stay on one shard. Choosing that key well is the big design decision.
Timeline
- 2005
Damien Katz starts CouchDB
- 2006
RFC 4627 describes JSON
- 2008
CouchDB becomes a top-level Apache project
- 2009
MongoDB’s first official release, 0.8
- 2014
PostgreSQL 9.4 adds the
jsonbtype - 2018
MongoDB 4.0 adds multi-document transactions; licence moves to SSPL
- 2019
AWS launches DocumentDB, compatible with MongoDB
- RFC 4627: The application/json media type for JSON (Douglas Crockford, Jul 2006)
- Wikipedia: Apache CouchDB, on Damien Katz and the April 2005 start
- Apache Incubator: CouchDB project status (graduated 2008-11-19)
- MongoDB: Our story
- mongodb/mongo on GitHub: tag r0.8.0, first official release (Feb 2009)
- MongoDB press release: MongoDB acquires WiredTiger (Dec 2014)
- MongoDB blog: multi-document ACID transactions (2018)
- MongoDB: Server Side Public License FAQ (Oct 2018)
- AWS What’s New: Amazon DocumentDB (with MongoDB compatibility) generally available (Jan 2019)
- PostgreSQL: PostgreSQL 9.4 released, with JSONB (Dec 2014)
Sources19
- DB-Engines: Document stores
- MongoDB manual: BSON types
- MongoDB manual: Query on embedded documents (dot notation)
- MongoDB manual: Multikey indexes (indexes on arrays)
- MongoDB manual: $set (replace the value of one field)
- MongoDB manual: Aggregation operations
- MongoDB manual: $lookup (joins with another collection)
- MongoDB manual: Data modeling (flexible schema, embedding)
- MongoDB manual: Schema validation
- MongoDB manual: Transactions (greater cost than single-document writes)
- MongoDB manual: Sharded cluster query routing (targeted and broadcast operations)
- PyMongo docs
- Amazon DocumentDB Developer Guide: What is Amazon DocumentDB?
- DynamoDB Developer Guide: What is Amazon DynamoDB? (key-value and document models)
- Google Cloud: Firestore overview
- Microsoft Learn: Azure Cosmos DB introduction
- Microsoft Learn: What is Azure Cosmos DB for MongoDB?
- Apache CouchDB docs: Why CouchDB?
- FerretDB on GitHub: MongoDB-compatible, on PostgreSQL (Apache 2.0)