- MongoDB interviews have three layers: the document model (BSON, _id, 16 MB limit), query performance (indexes, the ESR rule, explain plans, aggregation), and distribution (replica sets, write/read concern, sharding).
- The question that decides most interviews: embed or reference? Answer it from access patterns and growth, not from habit.
- Know how to read
explain("executionStats"): COLLSCAN vs IXSCAN,totalDocsExaminedvsnReturned, and in-memory SORT stages. - For sharding, a monotonically increasing shard key (timestamp, ObjectId) is the classic wrong answer. Explain why.
- Version-aware answers win: multi-document transactions since 4.0/4.2, resharding since 5.0, time-series collections since 5.0.
MongoDB questions show up in backend, full-stack and MERN-stack interviews, and almost always in the resume deep dive if it is on your resume. Interviewers rarely want syntax trivia. They want to know whether you can model data for the queries you have, keep those queries fast with the right indexes, and reason about what happens when a primary dies or one shard gets all the writes.
Run the examples in mongosh against a local instance or a free Atlas cluster as you read. The answers are concise enough to say aloud; the follow-ups are what experienced interviewers ask next.
How MongoDB Is Tested in Interviews
Concepts
Document vs relational, BSON types, replica set roles, what a write concern is. Common for freshers and in screening rounds.
Write it live
"Top 5 cities by order value last month" as an aggregation pipeline, or an update with array operators.
Debug a slow query
Given a query and an explain output, choose the index. Tests the ESR rule and covered queries.
Model and scale
Schema for a chat app or product catalog, embed vs reference, shard key choice, consistency settings.
MongoDB Fundamentals: Questions 1-10
Q1. What is MongoDB and how is it different from a relational database?
MongoDB is a document database: data is stored as BSON documents (JSON-like, with richer types) grouped into collections, without a fixed table schema. The main differences from an RDBMS are that related data is usually embedded in one document instead of normalized across tables, joins are possible ($lookup) but not the default tool, schemas can evolve per document, and horizontal scaling through sharding is built in. Relational databases give you stronger schema enforcement, mature joins and SQL; MongoDB optimizes for reading and writing whole aggregates in one operation.
Q2. What is BSON and why not plain JSON?
BSON is Binary JSON. It adds types JSON lacks (ObjectId, Date, 32/64-bit integers, Decimal128, binary data), stores field lengths so the server can skip over fields quickly, and is cheaper to parse. The Decimal128 point matters for money: storing ₹ amounts as doubles invites rounding errors, so use Decimal128 or integer paise.
Q3. What is the _id field and what is inside an ObjectId?
Every document needs a unique _id, which is automatically indexed. If you do not supply one, the driver generates a 12-byte ObjectId: a 4-byte timestamp (seconds since epoch), a 5-byte random value unique per process, and a 3-byte incrementing counter. Because the timestamp leads, ObjectIds are roughly increasing, and you can extract the creation time with getTimestamp(). That rough monotonicity is exactly why ObjectId is a poor ranged shard key (Q42).
Q4. What is the maximum document size, and what do you do about large data?
16 MB. For large files use GridFS, which splits a file into chunks (255 KB by default) across two collections, or more commonly store the file in object storage and keep the URL in the document. If an ordinary document approaches the limit, it almost always has an unbounded array (all comments on a viral post, all events from a device) and needs a different schema.
Q5. Collection vs document vs database?
A database holds collections; a collection holds documents; a document holds fields. Collections are roughly analogous to tables but documents in a collection need not share fields. You can enforce structure with schema validation using $jsonSchema on the collection.
Q6. Is MongoDB schemaless?
It is schema-flexible, not schemaless. The schema lives in your application and indexes even if the database does not enforce it. In production, teams add $jsonSchema validators and use an ODM like Mongoose to enforce types. Saying "MongoDB means no schema design" is a red flag in interviews; schema design matters more, not less, because it is driven by queries.
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["userId", "amountPaise", "status"],
properties: {
amountPaise: { bsonType: "long", minimum: 0 },
status: { enum: ["CREATED", "PAID", "SHIPPED", "CANCELLED"] }
}
}
},
validationAction: "error"
})
Q7. Which storage engine does MongoDB use?
WiredTiger, the default since 3.2. It provides document-level concurrency control (two writes to different documents in one collection do not block each other), compression (snappy by default for collections, prefix compression for indexes), and an internal cache that by default is the larger of 50% of (RAM minus 1 GB) or 256 MB. It uses checkpoints plus a write-ahead journal for durability.
Q8. Is a single-document write atomic?
Yes, always, including updates that touch many fields and embedded arrays inside that document. This is the foundation of MongoDB schema design: if data that must change together lives in one document, you get atomicity without a transaction.
Q9. Does MongoDB support multi-document transactions?
Yes: since 4.0 on replica sets and 4.2 on sharded clusters, with snapshot isolation and all-or-nothing commit. They have costs: extra coordination, a default 60-second runtime limit, and cache pressure from long-running transactions. Use them for genuinely cross-document invariants (moving money between two wallet documents), not as a substitute for modelling.
const session = db.getMongo().startSession();
const wallets = session.getDatabase("pay").wallets;
session.startTransaction({ readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } });
try {
const r = wallets.updateOne({ _id: "alice", balance: { $gte: 500 } }, { $inc: { balance: -500 } });
if (r.modifiedCount !== 1) throw new Error("insufficient funds");
wallets.updateOne({ _id: "bob" }, { $inc: { balance: 500 } });
session.commitTransaction();
} catch (e) {
session.abortTransaction();
throw e;
} finally {
session.endSession();
}
Q10. Where does MongoDB fit in CAP terms?
A replica set has a single primary for writes. During a partition, the side without a majority cannot elect a primary and stops accepting writes, so with majority write and read concerns MongoDB behaves as CP. With looser settings (w:1, reading from secondaries) you trade consistency for latency and availability. The honest answer is that it is tunable per operation. Our CAP theorem guide explains why that framing is better than labels.
Queries and CRUD: Questions 11-16
Q11. How do find, projection, sort and limit work together?
db.orders.find(
{ city: "Bengaluru", status: "PAID", amountPaise: { $gte: 100000 } }, // filter
{ _id: 0, orderId: 1, amountPaise: 1, createdAt: 1 } // projection
).sort({ createdAt: -1 }).limit(20)
The server applies the filter, then sort, then skip/limit, then projection, regardless of the order you chain them in the shell. Projection reduces network transfer, and if every projected field is in the index, the query can be covered (Q22).
Q12. Why is skip-based pagination slow, and what is the alternative?
skip(100000) still walks and discards 100,000 index entries or documents, so deep pages get slower linearly. Use range (keyset) pagination: remember the last createdAt and _id seen and ask for documents after them. It uses the index directly and is stable when new documents arrive.
// next page after the last item of the previous page
db.orders.find({
city: "Bengaluru",
$or: [
{ createdAt: { $lt: lastCreatedAt } },
{ createdAt: lastCreatedAt, _id: { $lt: lastId } }
]
}).sort({ createdAt: -1, _id: -1 }).limit(20)
Q13. What are the important update operators?
$set and $unset for fields; $inc for atomic counters; $push (with $each, $slice, $sort), $addToSet and $pull for arrays; $min/$max for conditional updates. Using $inc instead of read-then-write avoids lost updates without a transaction. $push with $slice: -50 keeps only the last 50 items, a neat fix for unbounded arrays like "recently viewed products".
Q14. What is an upsert?
An update with upsert: true inserts a new document if no document matches the filter. Use $setOnInsert for fields that should be written only on creation. Interview follow-up: two concurrent upserts with the same filter can both insert unless a unique index exists on the filter fields; with it, one fails with a duplicate key error that the driver can retry.
Q15. How do you query arrays and embedded documents?
Dot notation reaches into embedded documents ({"address.pincode": "560001"}). A condition on an array field matches if any element matches. To require that one element satisfy several conditions together, use $elemMatch; without it, {"items.sku": "A", "items.qty": {$gt: 5}} can match a document where one item is sku A and a different item has qty 6. This difference is a favourite trick question.
Q16. What is the difference between deleteMany and dropping a collection?
deleteMany({}) removes documents one by one, generates an oplog entry per document, and keeps indexes. drop() removes the collection and its indexes in one metadata operation and is far faster. For expiring data automatically, use a TTL index instead of cron-driven deletes (Q21).
Indexing: Questions 17-26
Indexing is where MongoDB interviews are won or lost. Indexes are B-tree structures, so everything in our B-tree indexing explainer applies.
Q17. What types of indexes does MongoDB support?
| Index | Use |
|---|---|
| Single field | Equality or range on one field |
| Compound | Multiple fields; order matters (prefix rule, ESR) |
| Multikey | Created automatically when an indexed field is an array; one entry per element |
| Text | Basic full-text search with stemming and stop words |
| 2dsphere | Geospatial queries: $near, $geoWithin |
| Hashed | Hashed shard keys, equality only |
| Wildcard | Unknown or arbitrary field names, such as user-defined attributes |
| TTL | Auto-delete documents after a time |
| Partial / sparse | Index only documents matching a filter / having the field |
| Unique | Enforce uniqueness (can combine with partial) |
Q18. What is the prefix rule for compound indexes?
An index on {a: 1, b: 1, c: 1} can serve queries on a, on a, b, and on a, b, c, but not efficiently on b alone or b, c, because the index is sorted by a first. So an index on {a, b} is redundant if {a, b, c} exists.
Q19. Explain the ESR rule with an example.
Order compound index fields as Equality, Sort, Range. Take this query:
db.orders.find({ city: "Pune", amountPaise: { $gte: 50000 } }).sort({ createdAt: -1 })
{city: 1, amountPaise: 1, createdAt: -1}(E, R, S): within Pune, entries are ordered by amount, so the results are not increatedAtorder and MongoDB adds an in-memory SORT stage. Bad at scale.{city: 1, createdAt: -1, amountPaise: 1}(E, S, R): within Pune, entries are already increatedAtorder; the amount condition is checked against index keys as it walks. No in-memory sort, and withlimit(20)it can stop early.
The E-S-R index may examine a few more keys, but avoiding a blocking sort usually wins, especially with a limit.
Q20. What is a multikey index and what is its restriction?
When you index a field that holds an array, MongoDB creates an index entry per element, so {tags: 1} finds documents containing a tag. Restriction: a compound index can include at most one array field per document; indexing two parallel arrays would create a cross product of entries, so MongoDB rejects inserting a document where both are arrays.
Q21. How does a TTL index work?
db.otp_codes.createIndex({ createdAt: 1 }, { expireAfterSeconds: 300 })
A background task runs roughly every 60 seconds and deletes documents whose date field is older than the threshold. So deletion is not instant: an OTP might live a minute past expiry, which means your code must still check expiry when validating. Good uses: OTPs, sessions, temporary carts, rate-limit buckets.
Q22. What is a covered query?
A query whose filter and projection fields are all in one index, with _id excluded unless it is in the index. MongoDB answers from the index alone without fetching documents; in explain output you will see totalDocsExamined: 0. Covered queries are the cheapest reads you can get, and a good answer to "how would you make this 10x faster".
Q23. How do you read an explain plan?
db.orders.find({ city: "Pune", status: "PAID" }).explain("executionStats")
Look for four things. The winning plan's stages: COLLSCAN means no index was used; IXSCAN followed by FETCH is normal. Compare totalKeysExamined, totalDocsExamined and nReturned: ideally all three are close. A SORT stage means an in-memory sort. And executionTimeMillis. If you examined 200,000 documents to return 20, the index is wrong or missing.
Q24. What are partial and sparse indexes?
A sparse index skips documents that lack the field. A partial index is more general: it indexes only documents matching a filter expression, such as {status: "ACTIVE"}. Partial indexes are smaller and faster to maintain. A classic use: a unique index on email only for documents where email exists, so many users without an email do not collide on null. The catch: the query must include the partial filter condition for the planner to use the index.
Q25. What is the cost of indexes?
Every insert, delete and update to an indexed field must update each index, so writes slow down and RAM fills up. Indexes perform best when the working set of index pages fits in the WiredTiger cache. Use $indexStats to find indexes that are never used and drop them. A collection with 15 indexes on a write-heavy path is a common finding in performance reviews.
Q26. How do you build an index on a large production collection?
Since 4.2, index builds use an optimized process that holds an exclusive lock only briefly at the start and end, so reads and writes continue during the build. On replica sets the build runs on all members together. Still schedule large builds off-peak, watch replication lag and disk, and for very large collections some teams use rolling builds member by member.
Aggregation Pipeline: Questions 27-33
Q27. What is the aggregation pipeline?
A sequence of stages where each stage transforms the stream of documents and passes it on, like Unix pipes. Core stages: $match (filter), $project/$addFields (reshape), $group (aggregate), $sort, $limit, $unwind (one document per array element), $lookup (join), $facet (multiple sub-pipelines), $bucket, and $merge/$out to write results.
Q28. Write a pipeline: top 5 cities by paid revenue last month, with order count and average order value.
db.orders.aggregate([
{ $match: {
status: "PAID",
createdAt: { $gte: ISODate("2026-09-01"), $lt: ISODate("2026-10-01") }
}},
{ $group: {
_id: "$city",
revenuePaise: { $sum: "$amountPaise" },
orders: { $sum: 1 },
avgOrderPaise: { $avg: "$amountPaise" }
}},
{ $sort: { revenuePaise: -1 } },
{ $limit: 5 },
{ $project: {
_id: 0, city: "$_id", orders: 1,
revenueRupees: { $divide: ["$revenuePaise", 100] },
avgOrderRupees: { $round: [{ $divide: ["$avgOrderPaise", 100] }, 2] }
}}
])
Talk through it: $match first so it can use an index on {status, createdAt} and shrink the stream; $group by city; sort and limit; reshape at the end. Interviewers like hearing why the order matters.
Q29. Why should $match come as early as possible?
Only stages at the start of the pipeline can use indexes, and every document filtered early is one fewer to group or sort. The optimizer moves some $match stages earlier automatically, but do not rely on it, and note that a $match on a field computed by $group cannot move before that group.
Q30. What does $unwind do, and what is the pitfall?
$unwind: "$items" outputs one document per array element, so you can group by item SKU. Pitfall: documents with an empty or missing array disappear unless you set preserveNullAndEmptyArrays: true. Also, unwinding large arrays multiplies document counts and memory.
Q31. How does $lookup work and when is it a smell?
$lookup performs a left outer join to another collection, either by local and foreign field equality or with a sub-pipeline. Make sure the foreign field is indexed, or every input document triggers a scan. If your hottest read path needs $lookup across several collections, you have probably modelled the data relationally; consider embedding or the extended reference pattern (Q48). $lookup against sharded foreign collections has been supported since 5.1.
Q32. What is the aggregation memory limit?
Each blocking stage such as $group or $sort is limited to 100 MB of RAM. Beyond that, the stage must spill to disk, which requires allowDiskUse: true in older versions; since 6.0 the server parameter allowDiskUseByDefault is on by default. Spilling works but is slow, so heavy analytics usually belong in a warehouse, an Atlas analytics node, or precomputed rollups.
Q33. What is $facet used for?
$facet runs several sub-pipelines on the same input in one pass. The textbook use is an e-commerce search page: one facet returns the page of products, another returns counts per brand, another counts per price bucket. One round-trip instead of three.
Replica Sets, Write Concern and Read Concern: Questions 34-39
Q34. What is a replica set?
A group of mongod processes holding the same data: one primary that takes all writes and some secondaries that replicate from it. The usual production setup is three data-bearing members, often across availability zones. A replica set can have up to 50 members, of which at most 7 vote.
Q35. How does replication work?
The primary records every write in the oplog, a capped collection in the local database. Secondaries tail the oplog and apply operations, which are idempotent so they can be safely replayed. If a secondary falls further behind than the oplog window (for example, it was down for longer than the oplog covers), it needs a full initial sync. Monitor replication lag and size the oplog for your write volume.
Q36. How does failover and election work?
Members exchange heartbeats every 2 seconds. If the primary is unreachable for the election timeout (10 seconds by default), an eligible secondary calls an election using a Raft-like protocol; the candidate with a majority of votes becomes primary. Typical failover takes a few seconds, and drivers with retryable writes (default on in modern drivers) retry a failed write once against the new primary. An arbiter votes but holds no data; it is discouraged in production because it does not help with majority writes.
Q37. What is write concern?
Write concern is how many members must acknowledge a write before the client gets success. w: 1: primary only (fast; can be lost if the primary dies before replicating, and such writes are rolled back after failover). w: "majority": a majority of voting members have it, so it survives any failover; this is the default since 5.0. j: true additionally waits for the journal on disk. Use majority for orders and payments; w: 1 may be acceptable for analytics events.
Q38. What are read concern and read preference?
They answer different questions. Read preference is which member to read from: primary (default), primaryPreferred, secondary, secondaryPreferred, nearest. Read concern is what data is acceptable: local (latest on that node, may be rolled back), majority (only majority-committed data), linearizable (reflects all majority writes acknowledged before the read, primary only), snapshot (for transactions).
Follow-up: "A user updates their profile and the page shows old data. Why?" Reads go to a lagging secondary. Fixes: read from the primary for that user's own data, or use a causally consistent session so reads see the session's earlier writes.
Q39. What are change streams?
Change streams let applications subscribe to inserts, updates and deletes on a collection, database or deployment, built on the oplog with resumable tokens. They are used for cache invalidation, syncing to Elasticsearch, pushing real-time updates, and the transactional outbox pattern. They require a replica set or sharded cluster, not a standalone server.
Sharding: Questions 40-45
Q40. What are the components of a sharded cluster?
Shards hold subsets of data, each a replica set. mongos routers look up which shard owns which key range and route queries. Config servers (a replica set) store the metadata. A balancer moves data between shards to keep them even. For the general theory, see our sharding strategies guide.
Q41. Ranged vs hashed vs zoned sharding?
Ranged sharding splits the key space into contiguous ranges (chunks), which makes range queries on the shard key efficient but risks hotspots. Hashed sharding hashes the key so writes spread evenly, but range queries on the key become scatter-gather. Zoned sharding pins key ranges to specific shards, for example keeping Indian users' data on shards in an Indian region for data-residency rules.
Q42. What makes a good shard key?
- High cardinality: many distinct values, so data can be split finely. A
statusfield with five values can never be split into more than five chunks. - Low frequency: no single value dominates. If 40% of orders belong to one large merchant, sharding by
merchantIdalone puts that merchant on one shard. - Non-monotonic: a timestamp or ObjectId key sends every new insert to the chunk holding the maximum value, so one shard takes all writes while others idle.
- Query-aligned: queries that include the shard key are targeted to one shard; queries without it are scatter-gather to all shards.
A common good answer: a compound key such as {customerId: 1, createdAt: 1}. Writes spread across customers, and "this customer's recent orders" hits one shard.
Q43. What are chunks and what does the balancer do?
Data is divided into chunks, contiguous ranges of shard-key values (default maximum 128 MB since 6.0; it was 64 MB earlier). The balancer migrates chunks from shards with more data to those with less. Migrations consume I/O and network, so teams sometimes restrict the balancing window to off-peak hours. A jumbo chunk is one that cannot be split because all its documents share one shard-key value, a symptom of a low-cardinality key.
Q44. Can you change a shard key?
Since 4.4 you can refine a shard key by adding suffix fields, and since 5.0 you can reshard a collection to a completely new key online; MongoDB copies data into the new distribution and switches over. It is expensive for large collections, so choosing well upfront still matters. Before 5.0 the answer was "dump and reload into a new collection".
Q45. When should you shard at all?
Later than most people think. Shard when the working set no longer fits in RAM on the largest practical machine, write throughput exceeds what one primary handles, or data size makes backups and restores too slow. Before that, fix indexes, schema and hardware. Sharding adds operational cost and makes non-targeted queries slower. If an interviewer asks you to "scale MongoDB", list vertical scaling, read replicas for stale-tolerant reads, and caching before sharding, then shard with a justified key.
Schema Design: Questions 46-50
Q46. Embedding vs referencing: how do you decide?
| Embed when | Reference when |
|---|---|
| Data is read together (order and its line items) | Data is often read independently (product details shown on many orders) |
| Relationship is one-to-few and bounded | One-to-many is large or unbounded (a post's comments, a device's readings) |
| Child has no meaning without the parent | Child is shared by many parents (many-to-many) |
| You need atomic updates across parent and child | Child is updated frequently and independently |
The rule of thumb: data that is accessed together should be stored together, but never embed something that grows without bound.
Q47. Design a schema for an e-commerce order.
{
"_id": "ORD-2026-000123",
"userId": "U-8812",
"status": "PAID",
"createdAt": { "$date": "2026-10-02T10:15:00Z" },
"shippingAddress": { "line1": "12 MG Road", "city": "Bengaluru", "pincode": "560001" },
"items": [
{ "sku": "SKU-77", "name": "Running Shoes", "pricePaise": 349900, "qty": 1 },
{ "sku": "SKU-12", "name": "Socks (3 pairs)", "pricePaise": 49900, "qty": 2 }
],
"totalPaise": 449700,
"payment": { "method": "UPI", "txnRef": "AXIS123456" }
}
Items and address are embedded because the order is read as a whole and must reflect prices and the address at purchase time; later product price changes must not rewrite history. The product catalogue stays a separate collection. Indexes: {userId: 1, createdAt: -1} for "my orders", {status: 1, createdAt: 1} for operations dashboards.
Q48. What are common MongoDB schema design patterns?
- Extended reference: copy the few fields you always display (customer name, phone) into the referencing document to avoid a lookup; accept that copies may need updating.
- Subset: embed only the 10 most recent reviews in the product; keep the rest in a reviews collection.
- Bucket: group time-series readings into one document per device per hour instead of one per reading. Since 5.0, native time-series collections do this automatically.
- Computed: maintain running totals (rating count and sum) on write instead of aggregating on every read.
- Outlier: handle the rare celebrity post with millions of likes using an overflow document, without distorting the schema for everyone else.
- Attribute: turn many sparse fields (screen size, RAM, fabric) into an array of
{k, v}pairs that one index can cover. - Polymorphic: store different shapes (credit card, UPI, netbanking payments) in one collection with a
typefield.
Q49. How would you model a chat application?
A conversations collection holds participants and a small lastMessage summary (extended reference) for the inbox screen. Messages go in a separate messages collection, one document per message, indexed on {conversationId: 1, sentAt: -1}, because a conversation's messages are unbounded. For very high volume, bucket messages per conversation per day or shard on conversationId so a conversation's messages live together and reads are targeted. Unread counts can be maintained per user per conversation with $inc.
Q50. MongoDB or PostgreSQL for a new service?
A balanced answer impresses more than loyalty to either. Choose MongoDB when the data is naturally hierarchical and read as aggregates, the shape varies across records (catalogues with category-specific attributes), and you expect to scale writes horizontally. Choose PostgreSQL when data is relational with many joins, you need strong constraints and complex transactions (ledgers, inventory with reservations), or analysts need SQL. PostgreSQL's JSONB narrows the gap for semi-structured fields. Our database choice guide has a fuller decision table.
Scenario Round Practice
Experienced candidates usually get a scenario rather than a list of questions. Practise these out loud, structuring each answer as diagnosis, fix, and trade-off.
- "The order history API takes 3 seconds." Run explain; if COLLSCAN or a large
totalDocsExamined, add{userId: 1, createdAt: -1}; replace skip pagination with keyset; project only fields the page shows. - "One shard is at 90% CPU, others at 20%." Check the shard key. Monotonic key means all inserts go to the top chunk; a dominant value means a jumbo chunk. Fix by resharding to a hashed or compound key.
- "Users occasionally see stale balances after topping up." Reads are going to secondaries. Read the user's own balance from the primary or use causally consistent sessions; keep secondary reads for stale-tolerant pages.
- "Documents hit the 16 MB limit." An array grows without bound. Move it to its own collection, or bucket it, and keep a bounded subset embedded.
- "We lost some writes after a failover." They were written with
w: 1and rolled back. Use majority write concern for critical data and enable retryable writes.
If your interviews also cover SQL, pair this with our DBMS interview questions; many companies ask both to see whether you can reason across data models rather than just recite one.
Frequently Asked Questions
Prepare for Backend Interviews
Prepflix's backend and system design track covers data modelling, indexing and sharding decisions the way product-company interviewers probe them.
Explore the Prepflix Course →