Overview
MongoDB is a document database that stores data as flexible BSON documents (JSON-like) grouped in collections. A document can contain nested objects and arrays, so related data that is read together can live in one document, avoiding joins. Schemas are flexible, although production systems usually enforce validation.
It scales reads with replica sets (one primary, several secondaries with automatic failover) and scales writes with sharding by a shard key. Modern MongoDB supports multi-document ACID transactions, but good designs still favor keeping related data in one document for performance.
Instead of splitting a customer's information across several ledgers (tables), you keep one folder with everything about them: addresses, preferences, recent orders. Opening one folder answers most questions.
When to use it
- Entities with nested, variable structure: catalogs, profiles, CMS content.
- Data that is read and written together as one unit.
- Rapidly evolving schemas.
- Horizontal scaling with a clear shard key.
Where it shows up in interviews
Recognize it when: products with different attributes per category.
- Design an e-commerce catalog
- Design a CMS
Recognize it when: model one-to-many relationships.
- Design a blog with comments
- Design user profiles with activity
Where it is used in real software
Many media and CMS platforms store articles and metadata in MongoDB for schema flexibility.
The managed service handles sharding, backups, search (Atlas Search), and vector search.
Applications subscribe to real-time changes, for example to update caches or search indexes.
Key terms
- Document / collection
- A BSON record / a group of documents.
- Embedding
- Nesting related data inside a document.
- Referencing
- Storing an ID that points to another document.
- Replica set
- Primary plus secondaries with automatic election.
- Shard key
- Field(s) that determine which shard stores a document.
How it works, step by step
- 1Identify access patterns
What is read together, and how often is it updated?
- 2Embed data read together
Addresses inside a user; the latest 10 reviews inside a product.
- 3Reference unbounded or shared data
All orders of a user live in an orders collection with userId.
- 4Index query fields
Compound indexes matching filters and sorts.
- 5Choose a shard key
High cardinality, even distribution, and present in most queries.
Embed or reference?
Rules of thumb
| Relationship | Choice | Reason |
|---|---|---|
| User and addresses (few) | Embed | Always read together, small, bounded |
| Product and latest 10 reviews | Embed a subset | Fast product page; full list elsewhere |
| User and all orders (unbounded) | Reference | Documents have a 16 MB limit and grow forever |
| Posts and tags (many-to-many) | Array of tag IDs or names | Query by tag with a multikey index |
NOWRelationship: User and addresses (few) | Choice: Embed | Reason: Always read together, small, bounded
Embed for data that is bounded and read together; reference for data that grows without limit or is shared across many documents.
Implementation
const products = db.collection("products"); await products.insertOne({ _id: "sku-1", name: "Trail Shoe", category: "shoes", attrs: { color: "red", sizes: [8, 9, 10] }, // varies by category topReviews: [{ user: "ana", rating: 5, text: "Great grip" }], price: { amountCents: 12900, currency: "USD" },}); await products.createIndex({ category: 1, "price.amountCents": 1 }); const cheapShoes = await products .find({ category: "shoes", "price.amountCents": { $lt: 10000 } }) .sort({ "price.amountCents": 1 }) .limit(20) .toArray(); // Atomic update of one document: push a review and keep only the latest 10await products.updateOne( { _id: "sku-1" }, { $push: { topReviews: { $each: [{ user: "bo", rating: 4, text: "Comfy" }], $slice: -10 } } },);Complexity and performance
Keep documents far smaller.
No transaction needed.
Replica set election.
Trade-offs
No enforced relations or foreign keys by default; use schema validation and application checks.
Embedding speeds reads but duplicates data that must be updated in several places.
Variants and related techniques
Stages ($match, $group, $lookup) for analytics and joins within MongoDB.
Optimized storage for timestamped data.
Common mistakes
- Unbounded arrays inside documents.
Fix: Move growing lists to their own collection.
- Monotonic shard keys like timestamps.
Fix: All inserts hit one shard; use hashed or compound keys.
- Modeling it like SQL with many references.
Fix: Excessive $lookup joins lose MongoDB's advantage.
Interview questions
When would you use MongoDB instead of PostgreSQL?
When entities have varied, nested structure read as a unit, schemas change frequently, and access is mostly by entity. For heavily relational data with many joins and strict integrity, PostgreSQL fits better.
How do you choose a shard key?
It should have high cardinality, distribute writes evenly, and appear in most queries so they target one shard. Avoid monotonically increasing values unless hashed.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Model a blog with posts and comments | Easy | Embed vs reference. |
| Design a product catalog with variable attributes | Medium | Indexes and documents. |