AlgoMaster Logo

Document Databases

Medium Priority17 min readUpdated October 4, 2026
AI Mock Interview

Practice this topic in a realistic system design interview

Listen to this chapter
Unlock Audio

Premium Video

This video is available to premium subscribers only

Unlock Full Access

In this chapter, we will learn what a document database is, how it stores and queries data, how to model data with embedding and references, and how document databases scale.

Loading simulation...

1. The Problem Document Databases Solve

Suppose we are building a product catalog for an online store.

The store sells many kinds of products. A shoe has sizes and a material, a laptop has a processor and memory, and a book has an author and a page count.

In a relational database, fitting all of these into one table is awkward:

  • One wide table. We could add a column for every possible attribute, but most columns would be empty for most products.
  • One table per type. We could create a separate table for each product type, but then every new product type needs a schema change.
  • A generic attributes table. We could use rows like (product_id, attribute_name, attribute_value), but that makes queries complex and slow.
Scroll
idnamesizesmaterialprocessormemory_gbauthorpages
1Trail Runner8,9,10meshNULLNULLNULLNULL
2ProBook 14NULLNULLM316NULLNULL
3System Design BasicsNULLNULLNULLNULLA. Singh320
One wide products table

There is a second problem. Displaying a single product page might require data from the products table, a variants table, an images table, and a specifications table. The application has to join all of them just to rebuild one product.

What if we could store the whole product, with all its details, as a single record that matches how the application already uses it? That is the idea behind a document database.

2. What Is a Document Database?

A document database stores data as documents. A document is a self-contained record, usually in a JSON-like format. MongoDB, for example, stores documents in a binary form of JSON called BSON.

Documents are grouped into collections. A collection is roughly similar to a table in a relational database.

Each document has a unique identifier. In MongoDB, this is a field called _id.

RelationalDocument
TableCollection
RowDocument
ColumnField
Join table / foreign keyEmbedded data or a reference to another document

Popular document databases include MongoDB, Couchbase, Google Firestore, and Azure Cosmos DB. Amazon DynamoDB can also store document-style items, although it is usually described as a key-value and document database.

Document IDs

The choice of _id matters more than it seems:

  • Database-generated IDs (like MongoDB's ObjectId) are convenient and roughly time-ordered.
  • UUIDs can be created by any service before writing. Random ones spread writes well, but make indexes less cache-friendly.
  • Application IDs, like an order number, are useful when the business already has one.

Time-ordered IDs keep recent records close together in the index, but can create a write hotspot if used as a shard key (more on that in Section 11).

3. The Structure of a Document

Let's look at what a product document might contain.

  • Simple fields, like the name, the brand, and the price.
  • An array, like a list of available sizes.
  • A nested object, like a specifications object with the material and the weight.
  • An array of objects, like a list of variants, where each variant has its own color, size, and stock count.

All of this lives in one document. So when the application needs the product page, it reads one document and gets everything it needs.

There are no joins, and the data is stored together on disk, so the database can usually load it in a single read. This is often called data locality.

The document matches the shape of the object in the application code, which makes it natural to work with.

4. Flexible Schema

The second big feature of document databases is a flexible schema.

In a relational database, every row in a table has the same columns. In a document database, two documents in the same collection can have completely different fields. The shoe document and the laptop document can both live in the same products collection, each with its own fields.

Adding a new field does not require a migration. The application simply starts writing documents with the new field.

This is useful when the data varies naturally, or when a product is changing quickly and the data model changes with it.

Flexibility Comes with Responsibility

If the database does not enforce structure, the application must handle it. Code that reads documents has to deal with missing fields, old formats, and unexpected types.

For this reason, many teams still add rules. MongoDB, for example, supports schema validation, where you can require certain fields and types while still allowing others to vary:

In production, "schemaless" should not mean "anything goes". Documents in a collection usually share a predictable core shape, with variation only where it is natural.

5. Querying Documents

Unlike a key-value store, a document database understands what is inside each document. So we can query by any field, not just the id.

Aggregation Pipeline

For more complex questions, MongoDB provides an aggregation pipeline. A pipeline is a series of stages, where each stage transforms the data and passes it to the next.

For example:

  1. The first stage could filter orders from last month.
  2. The next stage could group them by customer and sum the totals.
  3. The last stage could sort the customers by total spending.

MongoDB also has a $lookup stage that can join data from another collection. But it is generally more efficient to design documents so that most queries do not need joins at all.

6. Indexes

Just like relational databases, document databases need indexes to query efficiently. Without an index, a query has to scan every document in the collection.

Document databases support familiar index types, such as indexes on a single field and compound indexes on multiple fields. They also support indexes that are specific to documents.

Multikey Indexes

In MongoDB, an index on an array field is called a multikey index. It creates an index entry for each value in the array.

So if a product has sizes 8, 9, and 10, the index contains an entry for each size, and a search for size 9 can use the index directly.

Indexes on nested fields work as well.

Index TypeUse CaseExample
Single fieldQuery by one fieldbrand
CompoundQuery or sort by multiple fields{ brand, price }
MultikeyQuery values inside arrayssizes, variants.color
Nested fieldQuery inside embedded objectsspecifications.material
TextBasic text searchname, description
TTLExpire old documents automaticallysessions, temporary tokens

The trade-offs are the same as in any database. Indexes speed up reads, but every write must also update them, and they use extra memory and disk. Multikey indexes on large arrays can grow especially fast, since one document creates many entries.

7. Embedding vs Referencing

The most important decision when modeling data in a document database is whether to embed related data or reference it.

Embedding

Embedding means storing related data inside the same document. For example, an order document can embed its line items and the shipping address.

Referencing

Referencing means storing related data in a separate document and linking to it by id, similar to a foreign key. For example, an order document can store a customer_id that points to a separate customer document.

How to Decide

A useful rule of thumb:

  • Embed data that is read together, owned by the parent, and limited in size.
  • Reference data that is shared, updated independently, or can grow without limit.

Line items belong to one order, they are always displayed with the order, and an order has a limited number of them. So embedding them makes sense.

A customer places many orders, and their details can change. If we embedded the full customer in every order, updating their email would mean updating every order they ever placed. So we reference the customer instead.

FactorFavor EmbeddingFavor Referencing
Access patternRead together most of the timeRead independently
OwnershipOwned by the parentShared by many documents
Relationship sizeOne-to-one or one-to-fewOne-to-many or many-to-many
GrowthHas a clear limitCan grow without limit
UpdatesChanges with the parentChanges independently

Mixing Both

A common design is a mix of both. For example, an order might reference the customer by id, but also embed a snapshot of the shipping address as it was when the order was placed:

The address and item prices are saved copies. If Alice moves or the product price changes later, this order still shows what was true at purchase time, which is usually exactly what you want for order history.

In short, embedding gives you a single read and atomic updates, at the risk of duplicated data and documents that keep growing. Referencing keeps one official copy and smaller documents, at the cost of extra reads and no database-enforced foreign keys.

8. A Modeling Example: A Blog

Let's apply this to a blog. Each post has a title, an author, some tags, and comments.

  • Tags are small, belong to the post, and are read with it, so we embed them as an array.
  • The author is shared across many posts, so we store the author id, and maybe the author's name for display.
  • Comments are the interesting case.

At first, embedding comments in the post seems natural, because we show them together. But a popular post might receive tens of thousands of comments. The document would keep growing, and every new comment would rewrite a larger and larger document. MongoDB also limits a single document to 16 MB.

So comments are usually stored in their own collection, with each comment referencing the post id. The post might still embed the three most recent comments, so the page can load quickly without a second query.

This shows the general idea. Model documents around how the application reads and writes data, not around a fixed set of rules.

9. Updates and Transactions

Partial Updates

Document databases can update part of a document without rewriting the whole thing from the application. For example, we can set a single field, increment a counter, or push a new item onto an array.

Single-Document Atomicity

An important guarantee is that operations on a single document are atomic. If we update three fields in one document, either all three change or none do.

This is one reason embedding is useful. If an order and its line items live in one document, updating them together is automatically safe.

Multi-Document Transactions

For changes across multiple documents, MongoDB added multi-document ACID transactions in version 4.0, and extended them to sharded clusters in version 4.2. So we can, for example, create an order and reduce stock in a separate product document within one transaction.

But these transactions have more overhead than single-document operations. So a good document design keeps most related changes inside one document when possible.

10. Replication

Document databases usually replicate data across multiple servers for availability. In MongoDB, this is called a replica set.

A replica set has one primary and usually two or more secondaries.

  • All writes go to the primary, which records them in a log called the oplog.
  • The secondaries copy the oplog and apply the same changes.
  • If the primary fails, the remaining members hold an election, and one of the secondaries becomes the new primary. This usually happens automatically within seconds.

Write Concern and Read Preference

Applications can also control how safe each operation should be.

  • A write concern of majority means the write is only confirmed after most members have it. That protects the write even if the primary fails right after.
  • Reads can go to secondaries to spread load, but those reads might return slightly stale data, because secondaries can lag behind the primary.

11. Sharding

When a collection becomes too large or too busy for one replica set, document databases can shard it. The collection is split across multiple shards, and each shard is its own replica set.

The data is divided using a shard key, which is a field present in every document. For example, an orders collection might be sharded by customer_id.

MongoDB supports two strategies:

  • Ranged sharding, where nearby key values are stored together.
  • Hashed sharding, where keys are spread evenly using a hash.

The Router

A router (mongos in MongoDB) receives queries from the application and sends them to the right shard.

  • If the query includes the shard key, the router can send it to a single shard.
  • If it does not, the router has to send the query to every shard and combine the results. This is called a scatter-gather query, and it is much more expensive.

So the shard key should match your most common queries.

Hot Spots

A poor shard key can also create hot spots, where one shard receives most of the traffic.

Shard KeyProblem
statusOnly a few values, so data cannot spread across many shards
created_at or a time-ordered _id (ranged)Every new write lands on the shard holding the newest range
countryOne large country dominates one shard
customer_id (hashed)Spreads writes evenly, and "orders for this customer" stays a targeted query

12. Document vs Relational Databases

Let's compare document databases with relational databases.

Scroll
RelationalDocument
Data layoutNormalized tables, combined with joins at query timeRelated data kept together in one document, shaped for how it will be read
SchemaFixed, enforced by the databaseFlexible, with optional validation
Strong atComplex joins and ad hoc queries across many entitiesReading and writing whole objects quickly, when each request touches one main entity
TransactionsMulti-row ACID is the defaultSingle-document atomic; multi-document transactions available but costlier

The line between them has also blurred. PostgreSQL supports JSON columns with indexing, and MongoDB supports joins and transactions.

So the choice is less about features and more about which model fits your data and access patterns best.

13. When to Use a Document Database

A document database is a good fit when:

  • Your data is naturally shaped like objects with nested details. Product catalogs, content management systems, user profiles, and game state are common examples.
  • Records vary in structure, or the data model changes often.
  • Most requests read or write one main entity at a time, such as one product, one article, or one user.

It is less suited to:

  • Data with many relationships that need to be combined in different ways. Financial systems with complex reporting across accounts, transactions, and customers often fit better in a relational database.

And if you find yourself referencing everything and joining collections on almost every query, that is a sign the data may be more relational than document-shaped.

Summary

  • Document databases store data as JSON-like documents that can contain nested objects and arrays, grouped into collections.
  • Reading one document returns a whole object, with no joins, thanks to data locality.
  • A flexible schema lets documents in the same collection have different fields; schema validation adds guardrails.
  • Documents can be queried and indexed by any field, including nested fields and arrays (multikey indexes), and analyzed with the aggregation pipeline.
  • Good modeling comes down to deciding what to embed and what to reference, based on how the application uses the data.
  • Single-document writes are atomic; multi-document transactions exist but cost more.
  • With replica sets and sharding, document databases provide high availability and scale across many servers, as long as the shard key matches common queries.

Quiz

Document Databases Quiz

10 quizzes