- 25 Sep, 2026
- 0 Comments
- 52 Mins Read
Top MongoDB Interview Questions and Answers
-
What is MongoDB?
MongoDB is a document-oriented NoSQL database. It stores data in flexible, JSON-like documents called BSON (Binary JSON), rather than in traditional rows and columns. This design allows developers to model data in a way that mirrors how application code structures objects, eliminating the need for complex object-relational mapping. MongoDB supports high availability through built-in replication and automatic failover, horizontal scaling through native sharding, and multi-document ACID transactions .
-
What is a collection in MongoDB?
A collection is a grouping of MongoDB documents. It is the equivalent of a table in a relational database, but unlike a table, a collection does not enforce a rigid, predefined schema. Documents within the same collection can have different sets of fields and data types. Collections are created implicitly when you first insert data into them, or explicitly using the
db.createCollection()method if you need to specify options such as maximum size or schema validation rules . -
What is a document in MongoDB?
A document is the basic unit of data in MongoDB. It is an ordered set of field-value pairs, stored as BSON. The structure resembles a JSON object:
{ field1: value1, field2: value2, ... }. Field values can be any BSON data type, including other documents (embedded documents), arrays, and arrays of documents. Each document has a unique_idfield that acts as the primary key . -
What are the equivalents of tables, rows, and columns in MongoDB?
The mapping between relational database terminology and MongoDB concepts is as follows: a table corresponds to a collection; a row or tuple corresponds to a document; and a column corresponds to a field. Additionally, a table join corresponds to embedded documents or the
$lookupaggregation stage, and the primary key corresponds to the_idfield, which MongoDB provides by default . -
How do you take a MongoDB backup?
For self-managed deployments, the primary tools are
mongodumpandmongorestore.mongodumpconnects to a runningmongodinstance and exports data to BSON files or an archive file. You can back up an entire server, a specific database, a collection, or use a query to back up part of a collection. To ensure a consistent backup of a replica set, you must either use the--oplogoption to capture writes during the backup or stop all writes for the duration. Because these tools interact with a running database, they can impact performance. Alternative strategies include filesystem snapshots or MongoDB Atlas Cloud Backups. Always verify that backups are usable by restoring them to a test deployment . -
How do you create a MongoDB user?
Use the
db.createUser()method or thecreateUserdatabase command. You specify the username, password, and an array of roles that define the user’s permissions. For example:db.createUser({ user: "reportingUser", pwd: passwordPrompt(), roles: [ { role: "read", db: "reporting" } ] }). Therolesfield can include built-in roles or user-defined roles. You can also specifyauthenticationRestrictionsto limit the IP addresses or CIDR ranges from which the user can connect . -
How do you grant access/permissions in MongoDB?
MongoDB uses Role-Based Access Control (RBAC). You grant access by assigning one or more roles to a user. Roles contain privileges that define what actions a user can perform on a given resource (database, collection, or cluster). MongoDB provides built-in roles such as
read,readWrite,dbAdmin, andbackup. If built-in roles do not meet your needs, you can create user-defined roles with custom privileges. To grant a role, you can use thedb.grantRolesToUser()method, and to revoke it, usedb.revokeRolesFromUser(). -
What are the advantages of MongoDB over relational databases?
MongoDB offers several advantages over traditional relational databases. The most significant is schema flexibility — documents in the same collection can have different fields, so you can iterate quickly without running migrations. It provides horizontal scalability through native sharding, allowing you to distribute data across many servers as your dataset grows. Ease of development is another benefit because documents map naturally to objects in application code, reducing or eliminating the need for an ORM layer. For certain workloads — especially read-heavy, write-heavy, or semi-structured data — MongoDB delivers high performance by avoiding expensive joins and storing related data together in a single document. It also has built-in replication for high availability and multi-document ACID transactions for data integrity.
-
What are the data types supported by MongoDB?
MongoDB supports a rich set of BSON data types, including:
-
String — UTF-8 text
-
Integer — 32-bit or 64-bit signed integers
-
Double — 64-bit floating-point numbers
-
Decimal128 — 128-bit decimal for monetary calculations
-
Boolean — true or false
-
Array — ordered list of values
-
Object (embedded document) — nested document
-
Date — stored as milliseconds since the Unix epoch
-
Timestamp — internal MongoDB timestamp
-
ObjectId — 12-byte unique identifier
-
Binary data — raw bytes
-
Null — null value
-
Regular expression — for pattern matching
-
JavaScript — code without scope
-
JavaScript with scope — code with a scope document
-
MinKey / MaxKey — internal comparison keys
-
Symbol — deprecated, treated as string
-
-
What is the difference between _id and other fields in a document?
The
_idfield is a special mandatory field that acts as the primary key for every document in a collection. It must be unique within the collection, and MongoDB automatically creates it if you do not provide one, typically as an ObjectId. It is immutable — you cannot change the_idof an existing document. MongoDB automatically creates a unique index on the_idfield. All other fields are optional and store the actual application data. They can be of any BSON type, can be duplicated across documents, and can be added, modified, or removed freely. Unlike_id, other fields do not have a built-in index unless you create one. -
How do you create a database and collection in MongoDB?
In MongoDB, you do not need to explicitly create a database. A database is created implicitly the moment you first insert data into a collection within it. To switch to a database (and create it if it does not exist), use:
javascriptuse myDatabase
To create a collection explicitly, use:
javascriptdb.createCollection("myCollection")
You can also specify options such as:
javascriptdb.createCollection("logs", { capped: true, size: 10485760, max: 5000 })
If you insert a document into a non-existent collection, MongoDB creates the collection automatically:
javascriptdb.myCollection.insertOne({ name: "Alice", age: 30 })
-
How do you insert a document into a collection?
To insert a single document:
javascriptdb.collectionName.insertOne({ name: "Alice", age: 30, city: "Mumbai" })
To insert multiple documents at once:
javascriptdb.collectionName.insertMany([ { name: "Bob", age: 25 }, { name: "Charlie", age: 35 } ])
Both methods return a result object containing the
insertedId(forinsertOne) orinsertedIds(forinsertMany). If you insert a document without an_id, MongoDB generates an ObjectId automatically. -
How do you find documents in a collection?
Use the
find()method with an optional query document:javascriptdb.collectionName.find({ city: "Mumbai" })
To find all documents:
javascriptdb.collectionName.find()
To find one document:
javascriptdb.collectionName.findOne({ name: "Alice" })
You can also chain projection and sorting:
javascriptdb.collectionName.find( { age: { $gt: 25 } }, { name: 1, age: 1, _id: 0 } ).sort({ age: -1 })
-
How do you update documents in a collection?
To update a single document:
javascriptdb.collectionName.updateOne( { name: "Alice" }, { $set: { age: 31 } } )
To update multiple documents:
javascriptdb.collectionName.updateMany( { city: "Mumbai" }, { $set: { country: "India" } } )
Common update operators include:
-
$set— set field values -
$unset— remove fields -
$inc— increment numeric values -
$push— add to an array -
$pull— remove from an array -
$rename— rename a field
You can also use
replaceOne()to replace an entire document. -
-
How do you delete documents in a collection?
To delete a single document:
javascriptdb.collectionName.deleteOne({ name: "Alice" })
To delete multiple documents:
javascriptdb.collectionName.deleteMany({ city: "Mumbai" })
To delete all documents in a collection:
javascriptdb.collectionName.deleteMany({})
To drop the entire collection (including indexes):
javascriptdb.collectionName.drop()
deleteOne()anddeleteMany()return a result object with thedeletedCount. -
What are the different operators you can use for querying documents?
MongoDB provides a wide range of query operators:
Comparison operators:
-
$eq— equal to -
$ne— not equal to -
$gt— greater than -
$gte— greater than or equal to -
$lt— less than -
$lte— less than or equal to -
$in— matches any value in an array -
$nin— matches none of the values in an array
Logical operators:
-
$and— joins clauses with logical AND -
$or— joins clauses with logical OR -
$not— negates a query expression -
$nor— joins clauses with logical NOR
Element operators:
-
$exists— matches documents that have the field -
$type— matches documents where the field is of a specified type
Array operators:
-
$all— matches arrays containing all specified elements -
$elemMatch— matches arrays where at least one element matches all criteria -
$size— matches arrays of a specific size
Evaluation operators:
-
$regex— pattern matching -
$text— full-text search -
$where— JavaScript expression
-
-
What is an index in MongoDB?
An index in MongoDB is a data structure that stores a small portion of the collection’s data in an easy-to-traverse form. Without an index, MongoDB must perform a collection scan, reading every document to find matches. With an index, MongoDB can locate documents much faster by seeking directly to the relevant entries. Indexes are built on one or more fields and are stored in a B-tree structure. They improve query performance but add overhead to write operations because the index must be updated on every insert, update, or delete.
-
What are the different types of indexes in MongoDB?
MongoDB supports several index types:
-
Single field index — index on one field, either ascending or descending
-
Compound index — index on multiple fields, where the order matters
-
Multikey index — automatically created when indexing a field that holds an array
-
Text index — supports full-text search on string content
-
Hashed index — stores hashes of field values, used for sharding
-
Geospatial index — supports queries on geographic coordinates (
2dsphereand2d) -
Wildcard index — indexes all fields or a subset of fields dynamically
-
Unique index — enforces uniqueness on the indexed field
-
Sparse index — only indexes documents that contain the indexed field
-
TTL index — automatically removes documents after a specified time
-
Partial index — indexes only documents that match a filter expression
The default
_idindex is a unique single-field index created automatically. -
-
Explain the concept of sharding in MongoDB.
Sharding is MongoDB’s method for horizontal scaling. It distributes a collection’s data across multiple servers, called shards, based on a shard key. Each shard holds a subset of the data. The mongos router process directs queries from applications to the appropriate shard or shards. A config server replica set stores metadata about which data lives on which shard. Sharding allows you to store datasets larger than a single server can hold, and it distributes read and write throughput across multiple servers. Choosing a good shard key is critical — it should have high cardinality, low frequency, and be non-monotonic to ensure even data distribution.
-
What are the advantages and disadvantages of sharding?
Advantages:
-
Horizontal scalability — add more shards to increase capacity
-
Improved performance — reads and writes are distributed across shards
-
Larger datasets — store more data than a single server can hold
-
Geographic distribution — place shards closer to users
Disadvantages:
-
Increased complexity — more components to manage and monitor
-
Shard key selection — a poor shard key leads to hotspots and uneven distribution
-
Operational overhead — backups, upgrades, and maintenance are more involved
-
Query routing — queries that do not include the shard key must be broadcast to all shards
-
Cost — requires more hardware and infrastructure
-
-
What is the aggregation framework in MongoDB?
The aggregation framework is a pipeline-based data processing tool in MongoDB. It allows you to transform and analyze documents by passing them through a series of stages. Each stage takes input documents, performs an operation, and passes the output to the next stage. The aggregation pipeline is similar to SQL’s
GROUP BY,JOIN, andORDER BYbut far more flexible. It can perform filtering, grouping, sorting, reshaping, joining, and mathematical calculations. Aggregation pipelines are written as arrays of stage documents:javascriptdb.orders.aggregate([ { $match: { status: "completed" } }, { $group: { _id: "$customerId", total: { $sum: "$amount" } } }, { $sort: { total: -1 } } ])
-
What are some common stages used in the aggregation framework?
Common aggregation stages include:
-
$match— filters documents (likeWHERE) -
$group— groups documents by a key and computes aggregates (likeGROUP BY) -
$project— selects, renames, or excludes fields (likeSELECT) -
$sort— sorts documents (likeORDER BY) -
$limit— limits the number of documents -
$skip— skips a number of documents -
$unwind— deconstructs an array into multiple documents -
$lookup— performs a left outer join with another collection -
$count— counts documents -
$addFields— adds new computed fields -
$replaceRoot— replaces the document with a specified embedded document -
$facet— runs multiple pipelines on the same input -
$out— writes results to a collection -
$merge— merges results into a collection
-
-
What is the difference between a capped collection and a regular collection?
A capped collection is a fixed-size collection that overwrites the oldest documents when it reaches its maximum size. It preserves insertion order and supports high-throughput writes. Capped collections are useful for logs, event streams, and caching. They do not allow deletes (except when dropping the collection) and do not support updates that change document size. A regular collection can grow dynamically without a size limit, supports deletes and updates, and does not guarantee insertion order. Regular collections are the default and are suitable for most application data.
-
Explain replication in MongoDB.
Replication in MongoDB creates multiple copies of your data across different servers. The primary node receives all writes, and the secondary nodes replicate the primary’s oplog (operations log) to stay in sync. If the primary fails, an election is held among the secondaries, and one is promoted to primary. This provides fault tolerance and high availability. Replication also supports read preference, allowing applications to read from secondaries to distribute load. A replica set typically consists of at least three members: one primary and two secondaries. An arbiter can be added to break ties in elections without storing data.
-
What are the different types of replication sets in MongoDB?
MongoDB replication configurations include:
-
Single-node replica set — one primary only, used for development or testing
-
Standard replica set — one primary and two or more secondaries, providing automatic failover
-
Replica set with arbiter — two data-bearing nodes plus an arbiter that votes in elections but stores no data
-
Sharded cluster — each shard is itself a replica set, and config servers also run as a replica set
-
Delayed replica set member — a secondary that deliberately lags behind to protect against accidental data loss
-
Hidden replica set member — a secondary invisible to client applications, used for dedicated workloads like reporting
-
Priority-0 replica set member — a secondary that can never become primary
-
-
What is the difference between a document and a collection in MongoDB?
A document is the fundamental unit of data in MongoDB. It is a BSON object containing field-value pairs, similar to a row in a relational table but with a flexible schema. Each document has a unique
_idand can contain nested documents and arrays. A collection is a container that holds a group of documents. It is analogous to a table in a relational database, but it does not enforce a fixed schema. Collections are created implicitly when you insert the first document or explicitly usingcreateCollection(). Documents within a collection are typically related but can have entirely different structures. In short: a collection holds documents, and a document holds data. -
What is the MongoDB aggregation pipeline?
The MongoDB aggregation pipeline is a framework for processing and transforming data through a series of stages. Each stage takes input documents, performs an operation, and passes the output to the next stage. It is similar to an assembly line where raw data enters at one end and fully transformed results come out at the other. Pipelines are defined as an array of stage documents:
javascriptdb.orders.aggregate([ { $match: { status: "completed" } }, { $group: { _id: "$customerId", total: { $sum: "$amount" } } }, { $sort: { total: -1 } }, { $limit: 10 } ])
Key characteristics:
-
Stages execute sequentially in the order defined
-
Each stage can filter, reshape, group, sort, join, or compute data
-
The pipeline uses BSON documents as input and output
-
It is more powerful and flexible than simple
find()queries -
It can process data entirely server-side, reducing network overhead
Common use cases include reporting, real-time analytics, data transformation, and ETL operations.
What is the difference between MongoDB and Firebase?
Feature MongoDB Firebase Type Document-oriented NoSQL database Backend-as-a-Service (BaaS) platform Hosting Self-hosted or MongoDB Atlas (cloud) Fully managed by Google Data Model BSON documents in collections JSON tree (Realtime DB) or documents (Firestore) Query Language Rich query language with aggregation Limited querying, especially in Realtime DB Scalability Horizontal via sharding Automatic, but limited control Real-time Sync Change streams (not automatic) Built-in real-time synchronization Offline Support Not built-in Strong offline support in mobile SDKs Authentication Must be implemented separately Built-in authentication service Transactions Multi-document ACID transactions Limited transactions (better in Firestore) Vendor Lock-in Low — open source, portable High — tightly coupled to Google Cloud Best For Custom applications, complex queries, large datasets Rapid prototyping, mobile apps, real-time apps In short: MongoDB gives you full control and flexibility over data modeling and querying. Firebase gives you speed of development and built-in real-time features but with less control and higher vendor lock-in.
-
-
What is the difference between MongoDB and RDBMS?
Feature MongoDB RDBMS (e.g., MySQL, SQL Server) Data Model Document-oriented (BSON) Table-based (rows and columns) Schema Flexible / dynamic Fixed / predefined Query Language MongoDB Query Language (MQL) SQL Joins $lookup(limited)Native JOIN support Transactions Multi-document ACID (since 4.0) ACID by default Scaling Horizontal via sharding Primarily vertical Relationships Embedded documents or references Foreign keys Performance Fast for read-heavy, semi-structured data Fast for complex joins and structured data Use Cases Big data, IoT, real-time apps, catalogs Banking, ERP, CRM, structured reporting Normalization Denormalization preferred Normalization preferred MongoDB is better when your data is semi-structured, rapidly evolving, or needs horizontal scaling. RDBMS is better when your data is highly structured, relational, and requires strict consistency.
-
What is the MongoDB change streams?
Change streams allow applications to watch for real-time changes to data in a MongoDB deployment. They provide a push-based notification mechanism that reports inserts, updates, deletes, and replacements as they happen.
Key features:
-
Built on the oplog (operations log)
-
Available for replica sets and sharded clusters
-
Uses aggregation pipeline syntax for filtering
-
Returns resume tokens so you can resume after a failure
-
Supports filtering by operation type, database, or collection
Example:
javascriptconst changeStream = db.orders.watch([ { $match: { "operationType": "insert" } } ]) changeStream.on("change", (change) => { console.log("New order:", change.fullDocument) })
Common use cases: real-time dashboards, notifications, cache invalidation, ETL triggers, and microservice communication.
-
-
What is the MongoDB $lookup aggregation stage?
$lookupperforms a left outer join between two collections in the same database. It is the MongoDB equivalent of a SQLLEFT JOIN. For each document in the input collection, it finds matching documents in the foreign collection and adds them as an array field.Syntax:
javascript{ $lookup: { from: "foreignCollection", localField: "localFieldName", foreignField: "foreignFieldName", as: "outputArrayField" } }
Example:
javascriptdb.orders.aggregate([ { $lookup: { from: "customers", localField: "customerId", foreignField: "_id", as: "customerDetails" } } ])
Key points:
-
$lookupcan only join collections in the same database -
It supports pipeline-based lookups (since MongoDB 3.6) for more complex joins
-
It is not as efficient as SQL joins for large datasets
-
Results are returned as an array, even if only one match exists
-
-
What is the MongoDB TTL (Time to Live) index?
A TTL index is a special single-field index that automatically deletes documents after a specified amount of time. It is useful for session data, logs, caches, and temporary records.
How it works:
-
You create a TTL index on a field that contains a Date value
-
You specify an expireAfterSeconds value
-
A background thread runs every 60 seconds and removes expired documents
Example:
javascriptdb.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
Key points:
-
The indexed field must be a Date type or an array of Dates
-
Deletion is not immediate — there can be up to a 60-second delay
-
TTL indexes cannot be compound indexes
-
You can modify the expiration time using
collMod
-
-
What is the MongoDB backup and restore methods?
MongoDB provides several backup and restore strategies:
1. mongodump / mongorestore
-
mongodumpexports BSON files -
mongorestoreimports them back -
Works on running instances
-
Can back up a whole server, database, or collection
2. Filesystem snapshots
-
Use OS-level snapshots (LVM, EBS, etc.)
-
Must ensure journal and data files are consistent
-
Fast but requires storage-level support
3. MongoDB Atlas Cloud Backups
-
Fully managed continuous backups
-
Point-in-time recovery
-
Available only on Atlas
4. Oplog-based backups
-
Capture the oplog for point-in-time recovery
-
Used with
mongodump --oplog
5. Replica set backups
-
Back up from a secondary to avoid impacting the primary
-
Combine with
--oplogfor consistency
Best practices:
-
Always test restores regularly
-
Use replica sets for high availability
-
Schedule regular backups
-
Store backups off-site
-
Encrypt backups at rest and in transit
-
-
What is the MongoDB profiler?
The MongoDB profiler is a built-in tool that captures information about slow or all database operations. It records details about each operation, including the query, execution time, plan summary, and number of documents examined.
Profiling levels:
-
0 — Off (default)
-
1 — Log slow operations only (above
slowmsthreshold) -
2 — Log all operations
Enable profiling:
javascriptdb.setProfilingLevel(1, { slowms: 100 })
View profiler data:
javascriptdb.system.profile.find().sort({ ts: -1 }).limit(10)
Key fields:
-
op— operation type (query, insert, update, etc.) -
ns— namespace (database.collection) -
millis— execution time in milliseconds -
planSummary— index used -
docsExamined— documents scanned -
nreturned— documents returned
The profiler is useful for identifying slow queries, missing indexes, and performance bottlenecks.
-
-
What is the MongoDB Oplog?
The oplog (operations log) is a capped collection that records all write operations on the primary node of a replica set. Secondaries read the oplog and apply the operations to their own datasets to stay synchronized.
Key characteristics:
-
Stored in the local database as
local.oplog.rs -
It is a capped collection — old entries are overwritten when it reaches its size limit
-
Records idempotent operations so they can be applied multiple times safely
-
Used for replication, change streams, and point-in-time recovery
-
Size is configurable via
--oplogSize
Example entry:
javascript{ ts: Timestamp(1690000000, 1), op: "i", ns: "shop.orders", o: { _id: ObjectId("..."), item: "book", qty: 2 } }
Where
opcan bei(insert),u(update),d(delete), orc(command). -
-
What are the MongoDB best practices for schema design?
MongoDB schema design is about modeling data to match how your application queries and updates it. Best practices include:
1. Embed vs Reference
-
Embed when data is accessed together and has a 1:1 or 1:few relationship
-
Reference when data is large, shared, or has a 1:many or many:many relationship
2. Prefer Embedding for Read Performance
-
Embedding reduces the need for joins
-
Related data is stored in a single document
-
Ideal for read-heavy workloads
3. Avoid Unbounded Arrays
-
Arrays that grow indefinitely can hit the 16 MB document limit
-
Use the bucket pattern or separate collections for large arrays
4. Design for Your Query Patterns
-
Model data based on how it will be queried, not how it is normalized
-
Denormalization is common and encouraged
5. Use the Right Data Types
-
Use
Decimal128for money -
Use
Datefor timestamps -
Avoid storing numbers as strings
6. Index Wisely
-
Index fields used in queries, sorts, and joins
-
Use compound indexes for multi-field queries
-
Avoid over-indexing — it slows writes
7. Keep Documents Small
-
The maximum BSON document size is 16 MB
-
Large documents consume more memory and network bandwidth
8. Use Schema Validation
-
Enforce structure with
$jsonSchemavalidation rules -
Helps maintain data quality without losing flexibility
9. Plan for Sharding Early
-
Choose a shard key with high cardinality, low frequency, and non-monotonic values
-
A poor shard key causes hotspots and uneven distribution
10. Consider the Bucket Pattern
-
Group related data into buckets (e.g., one document per day of sensor readings)
-
Reduces document count and improves index efficiency
11. Use Transactions Sparingly
-
Multi-document transactions have overhead
-
Prefer embedding to avoid needing transactions
12. Document Your Schema
-
Even though MongoDB is schema-flexible, documenting your schema helps teams collaborate
-
-
What are MongoDB transactions?
MongoDB transactions provide ACID guarantees (Atomicity, Consistency, Isolation, Durability) for operations that span multiple documents, collections, databases, or shards . While a single-document write is always atomic in MongoDB, transactions are necessary when you need atomicity across multiple documents.
Key characteristics:
-
A transaction either applies all data changes or rolls back all changes upon abort
-
Until a transaction commits, its data changes are not visible outside the transaction
-
Transactions work on replica sets and sharded clusters
-
You can create collections and indexes within a transaction (except in cross-shard write transactions)
Important performance note: Distributed transactions incur higher performance costs compared to single-document writes. Proper schema design with embedded documents and arrays minimizes the need for transactions in most use cases .
Restrictions:
-
Cannot write to capped collections in transactions
-
Cannot read/write config, admin, or local databases
-
Cannot write to
system.*collections
-
-
What is Mongoose and how is it used with MongoDB?
Mongoose is an Object Data Modeling (ODM) library for Node.js that provides schema-based data modeling, validation, query building, and business logic hooks for MongoDB .
What Mongoose provides:
-
Schema definition — define field names, data types, and validation rules for documents in a collection
-
Model generation — create models from schemas to interact with collections
-
Application-level validation — enforce data validation rules before database operations
-
Business logic hooks — execute custom logic before or after database operations
-
Fluent API — build and execute database queries in a structured way
-
Population — reference documents from other collections, similar to SQL joins
Important distinction: Mongoose enforces schemas at the application level only. The MongoDB server itself is unaware of these constraints and will accept any valid BSON document . This means other applications or database tools can bypass Mongoose validation rules .
Trade-off: While Mongoose provides structure familiar to developers with relational database experience, it reduces flexibility. If your data structure changes, you must update the Mongoose schema .
-
-
What is the difference between MongoDB and Cassandra?
Both are NoSQL databases, but they are designed for different use cases and priorities.
Aspect MongoDB Cassandra Data Model Document-oriented (BSON) Wide-column store Query Language Rich query language with aggregation CQL (Cassandra Query Language) Consistency Highly customizable consistency levels Tunable consistency, favors availability Write Performance Good, but Cassandra often better for write-heavy workloads Excellent for write-heavy workloads Scalability Horizontal via sharding Horizontal, masterless architecture Best For General-purpose apps with complex queries Write-heavy workloads, time-series data, large-scale distributed systems Research indicates that MongoDB performs better in throughput for general workloads, while Cassandra excels in write-heavy scenarios . A performance evaluation also found that Cassandra had the best transaction processing per second, while MongoDB excelled in processes carried out per unit time .
-
What is MongoDB Atlas?
MongoDB Atlas is the fully managed cloud database service built by the same team that develops MongoDB . It simplifies deployment and management while providing flexibility to build resilient, high-performance applications on your preferred cloud provider.
Key features:
-
Multi-cloud deployment — available on AWS, Azure, and Google Cloud
-
125+ regions worldwide for low-latency access
-
Free tier with 512 MB storage for experimentation
-
Automated management — handles provisioning, scaling, backups, and updates
-
Security features — IP access lists, database user management, private networking, and full lifecycle encryption
-
Performance tools — Performance Advisor, index suggestions, and query optimization
-
Advanced capabilities — vector search, Atlas Search (full-text), and time-series data
-
Global clusters — place data closer to users for reduced latency
Atlas is designed to let you focus on building applications while it handles the operational complexity of database management.
-
-
What are MongoDB best practices for performance?
Key performance best practices include:
Indexing:
-
Create appropriate indexes to speed up queries and reduce database load
-
Use compound indexes for multi-field queries
-
Avoid over-indexing, which slows writes
-
Use the Performance Advisor (available on M10+ clusters) to get personalized index suggestions
Query Optimization:
-
Set up query targeting alerts to identify problematic queries
-
Review and optimize slow queries regularly
-
Use
explain()to analyze query execution plans
Monitoring:
-
Set up alerts for high CPU utilization, high memory usage, and slow query execution
-
Integrate with third-party application performance monitoring tools
Scaling:
-
Manually scale up before known traffic spikes rather than relying on auto-scaling, which may react too late
-
Use global clusters for users in multiple regions to reduce latency
Testing:
-
Perform load testing to simulate peak traffic conditions and identify bottlenecks
Schema Design:
-
Embed related data to avoid expensive joins
-
Keep documents small (under 16 MB limit)
-
Design for your query patterns
-
-
What is the difference between MongoDB and DynamoDB?
Aspect MongoDB DynamoDB Deployment Self-hosted, any cloud, or Atlas AWS-only (no on-premise) Setup Complexity Requires active configuration and management (unless using Atlas) Simple, fully managed by AWS Query Capabilities Rich queries, aggregation, full-text search Limited querying; requires predefined access patterns Data Model Document-oriented with flexible schema Key-value and document-oriented Primary Key Types Any field String, number, or binary only Max Document Size 16 MB 400 KB Pricing Model Instance-based or Atlas consumption Throughput-based (read/write capacity) Security Must be configured; disabled auth by default IAM-based, secure by default Ecosystem Broad language support, extensive tooling Deep AWS integration Best For General-purpose, complex queries, dynamic schemas Predefined access patterns, AWS-native apps, session management DynamoDB advantages: Serverless, seamless AWS integration, simple setup, predictable performance at scale .
DynamoDB limitations: Limited query flexibility, vendor lock-in to AWS, throughput-based pricing can cause bill spikes .
MongoDB advantages: Rich querying, flexible schema, portable across clouds, strong consistency options .
-
What is the difference between MongoDB and Redis?
Redis is an in-memory key-value store primarily used for caching, while MongoDB is a document database for persistent storage.
Aspect MongoDB Redis Data Model Document (BSON) Key-value, strings, lists, sets, hashes Storage Disk-based with memory caching Primarily in-memory with optional persistence Query Capabilities Rich queries, aggregation, joins Basic key lookups, some data structure operations Consistency Highly customizable consistency levels Prioritizes availability and performance over consistency Geospatial Performance Overall superior performance and scalability for geospatial data Best performance for geospatial data storage Use Cases General-purpose database, complex queries Caching, session management, real-time analytics, pub/sub Throughput Good Excellent (best throughput among evaluated DBMS) Key takeaway: Redis is optimized for speed and simplicity as an in-memory store. MongoDB is optimized for flexibility and persistence with rich querying. They are often used together — Redis for caching and MongoDB for the primary datastore .
-
What is the difference between MongoDB and Elasticsearch?
Elasticsearch is a distributed search and analytics engine built on Apache Lucene, while MongoDB is a general-purpose document database .
Aspect MongoDB Elasticsearch Primary Purpose Document storage and retrieval Search and analytics Data Model Document (BSON) Document (JSON) with inverted indexes Indexing Secondary indexes on fields All fields automatically indexed Query Type Rich queries, aggregation Full-text search, structured queries Geospatial Overall superior performance and scalability Relatively constant performance regardless of caching Consistency ACID transactions, customizable consistency Eventually consistent Best For Primary application database Search functionality, log analytics, text search Note: MongoDB Atlas now integrates Atlas Search, which provides Elasticsearch-like full-text search capabilities without requiring a separate Elasticsearch deployment . This blurs the line between the two for search use cases.
-
What are MongoDB capped collections?
Capped collections are fixed-size collections that insert and retrieve documents based on insertion order. They work like circular buffers: once the allocated space is full, new documents overwrite the oldest documents .
Key characteristics:
-
Fixed size defined at creation with
sizeparameter -
Insertion order preserved — documents are returned in the order they were inserted
-
Automatic overwriting — oldest documents are deleted when space runs out
-
No sharding — cannot be sharded
-
No transactions — cannot write to capped collections in transactions
-
Avoid updates — updates that expand documents can exceed allocated space and cause unexpected behavior
Creating a capped collection:
javascriptdb.createCollection("log", { capped: true, size: 100000 })
Common use case: Storing log information. When the collection reaches its maximum size, old log entries are automatically replaced with new ones .
Important note: MongoDB documentation states that TTL indexes generally offer better performance and more flexibility than capped collections. TTL indexes expire data from normal collections based on a date field . Consider using TTL indexes before opting for capped collections.
The oplog (operations log) in replica sets uses a capped collection, though it can grow beyond its configured limit to avoid deleting the majority commit point .
-
-
What is the difference between MongoDB and CouchDB?
Both are document-oriented NoSQL databases that store JSON documents and support distributed deployment, but they differ in architecture and priorities .
Aspect MongoDB CouchDB API Database connection with query language REST/JSON API over HTTP CAP Focus Prioritizes Consistency and Partition Tolerance Prioritizes Availability and Partition Tolerance Replication Replica sets with primary-secondary model Multi-master replication (Couch Replication Protocol) Query Language MongoDB Query Language (MQL) with aggregation JavaScript MapReduce views Commercial Support MongoDB Inc. offers Enterprise and Atlas Apache project, no official commercial service Popularity More widely adopted and supported Niche, focused on offline-first and sync use cases Best For General-purpose applications, complex queries, large datasets Simple distributed systems, offline-capable web apps, high availability scenarios Key differences summarized:
-
CouchDB excels at offline-first and multi-master replication scenarios, with a simple HTTP API
-
MongoDB excels at complex querying, high performance with large datasets, and has a much larger ecosystem and commercial support
A comparative analysis found that MongoDB is suitable for advanced projects requiring high performance with large data volumes, while CouchDB is better for simpler distributed systems and web applications where simplicity, fault tolerance, and high availability are prioritiesÂ
-
-
res.send()vsres.json()in Express.jsThe core difference is that
res.json()is purpose-built for JSON whileres.send()is a general-purpose method that adapts its behavior based on what you give it.res.json()always sets theContent-Typeheader toapplication/jsonand converts the argument to a JSON string usingJSON.stringify(). It can handle any JSON-serializable value, includingnullandundefined, without throwing errors.res.send()inspects the type of the argument and sets theContent-Typeaccordingly:-
String →
text/html -
Buffer →
application/octet-stream -
Object or Array → Express automatically converts it to JSON and sets
application/json
So when you pass an object to
res.send(), it ends up behaving similarly tores.json(). The practical recommendation: useres.json()when you explicitly intend to send JSON, andres.send()for plain text or raw buffers. -
-
The
_idField in MongoDB vs. Primary Key in SQLBoth serve as unique identifiers for records, but they differ in flexibility and generation.
SQL Primary Key: You define which column (or combination of columns) is the primary key. It must be unique, cannot be null, and is typically an auto-incrementing integer or a UUID. The database enforces this constraint strictly.
MongoDB
_id: Every document in a collection automatically has an_idfield that acts as the primary key. Key differences:-
Automatic generation: If you don’t provide an
_id, MongoDB generates one as anObjectId(a 12-byte unique value) -
Custom values allowed: You can insert your own
_idvalue (like an integer or UUID) instead of letting MongoDB generate one -
Always included:
find()queries return_idby default unless you explicitly exclude it via projection
The
_idfield is immutable and uniquely indexed, just like a primary key, but it is always present without you having to define it in a schema. -
-
useEffectDependency ArrayThe dependency array tells React which reactive values the Effect depends on. React compares these values between renders and only re-runs the Effect if one of them changed.
What belongs in the array: Every prop and every variable or function declared inside your component that the Effect reads is “reactive” and must be listed. The linter will flag missing dependencies as a warning.
If you leave it out entirely: The Effect runs after every single render. This is rarely what you want because it can cause infinite loops or unnecessary performance overhead.
If you pass an empty array
[]: The Effect runs once after the initial mount and never again. This is useful for one-time setup like subscribing to an event or fetching initial data.The trap with objects and functions: If your Effect depends on an object or function created inside the component body, it will re-run on every render because React creates a new reference each time. The fix is to move the object or function inside the Effect, or wrap it in
useCallback/useMemo. -
Node.js Single-Threaded Request Handling
Node.js runs your JavaScript application logic on a single thread, but it delegates blocking work to a background thread pool.
The Event Loop: This is the core mechanism. It continuously checks a queue of pending tasks. When a request arrives, its handler is queued. The event loop picks up the handler and executes its JavaScript.
Non-blocking I/O: When your code performs a database query, file read, or network call, Node.js does not wait for the result. Instead, it hands the operation to the internal thread pool (via libuv) and registers a callback. The event loop moves on to the next task.
When the I/O completes: The background thread places the callback back into the event loop’s queue. The event loop picks it up and runs the rest of your handler.
The catch: If your JavaScript does something CPU-intensive synchronously (like a massive
forloop), it blocks the event loop. No other requests can be processed until it finishes. For heavy computation, you should offload work toworker_threadsorchild_process. -
Form Submission in a MERN Application
Here is the flow when a user submits a form:
1. Frontend (React): The user clicks submit. React’s
onSubmithandler fires, typically capturing the form data into state or a form library like Formik.2. Sending the request: An HTTP client like Axios or
fetchsends aPOSTrequest to the backend API endpoint (e.g.,/api/users). The form data is sent as JSON in the request body.3. Backend (Express/Node): The request hits an Express route handler. Middleware like
body-parser(or Express’s built-inexpress.json()) parses the JSON body so you can access it asreq.body.4. Server logic: The handler validates the data, applies business logic, and prepares a response. If user registration, it might hash the password and generate a token.
5. Database (MongoDB): The handler uses a MongoDB driver or Mongoose to insert or update documents. For example,
User.create(req.body)inserts a new user document.6. Response back: The server sends a response (usually JSON) using
res.json()with a success message, the created resource, or an error.7. Frontend update: The React app receives the response. It can update state, show a success message, redirect the user, or display validation errors. In Redux-based apps, the response data is dispatched to reducers, which update the store, causing components to re-render.
-
AI-Powered Knowledge Base: Implementing Semantic Search
Scenario: Users ask natural-language questions, and the system must retrieve the most relevant documents.
To implement semantic search in MongoDB, you leverage Vector Search powered by embeddings and the
$vectorSearchaggregation stage.Step 1: Generate and Store Embeddings
First, you must convert your documents’ text into high-dimensional numerical vectors (embeddings) using a machine learning model (e.g., OpenAI, Voyage AI, or a local model like Sentence Transformers). These embeddings capture the semantic meaning of the text.You store these vectors directly in your MongoDB documents alongside the original text. In MongoDB, embeddings are stored as BSON Binary (Float32) data.
python# Example using Sentence Transformers from sentence_transformers import SentenceTransformer model = SentenceTransformer("all-MiniLM-L6-v2") doc = {"title": "MongoDB Guide", "content": "MongoDB is a document database..."} doc["embedding"] = model.encode(doc["content"]).tolist() collection.insert_one(doc)
Step 2: Create a Vector Search Index
You must create a Vector Search Index (using HNSW for Approximate Nearest Neighbor search) on the field containing your embeddings. This index enables fast similarity comparisons. You specify the number of dimensions (which must match your embedding model) and the similarity metric (e.g., cosine, dotProduct, euclidean).Step 3: Perform the Semantic Query
When a user asks a question, you convert that query into an embedding using the same model. Then, you run an aggregation pipeline starting with the$vectorSearchstage. This stage compares the query vector against the indexed document vectors and returns the top-k most semantically similar documents, even if they don’t share exact keywords.javascriptdb.knowledge_base.aggregate([ { $vectorSearch: { index: "vector_index", path: "embedding", queryVector: [0.12, -0.45, ...], // Embedding of the user's question numCandidates: 100, limit: 5 } } ])
-
E-Commerce Platform: Designing Hybrid Search
Scenario: Users search for “comfortable running shoes,” requiring both keyword precision and semantic understanding.
Hybrid search combines the precision of Full-Text Search (BM25) with the semantic recall of Vector Search. MongoDB natively supports this through the
$rankFusionor$scoreFusionaggregation stages.The Concept:
-
Full-Text Search excels at matching exact terms, synonyms, and handling specific product names.
-
Vector Search excels at understanding intent and context (e.g., understanding “comfortable” relates to cushioning or support, not just the word “comfortable” appearing in the description).
Implementation:
You define sub-pipelines for both search types within the$rankFusionstage. MongoDB runs them in parallel and merges the results using algorithms like Reciprocal Rank Fusion (RRF), which combines the rankings from both searches into a single, unified result set.javascriptdb.products.aggregate([ { $rankFusion: { input: { pipelines: { fullTextSearch: [ { $search: { index: "default", text: { query: "comfortable running shoes", path: "description" } } }, { $limit: 20 } ], vectorSearch: [ { $vectorSearch: { index: "vector_index", path: "embedding", queryVector: QUERY_VECTOR, numCandidates: 100, limit: 20 } } ] } }, combination: { weights: { fullTextSearch: 0.3, vectorSearch: 0.7 } } } }, { $limit: 10 } ])
This approach ensures that a product matching the exact phrase “running shoes” ranks highly, but a product described as “cushioned athletic footwear for jogging” can also appear due to its semantic relevance to “comfortable running shoes.”
-
-
E-Learning Platform: Embedding vs. Referencing
Scenario: Designing a schema where courses have thousands of students and reviews.
For this scenario, the decision depends on the specific access pattern and data size. You should generally use Referencing for Students and likely Referencing (or a hybrid Subset pattern) for Reviews.
Students: Reference
-
Reason: The relationship between courses and students is typically Many-to-Many. A student enrolls in multiple courses, and a course has many students. If you embedded student details inside the course document, you would duplicate massive amounts of data, and updating a student’s name would require updating every course document they are enrolled in.
-
Model: Store students in their own collection. In the course document (or a separate
enrollmentscollection), store an array ofstudent_idreferences. When you need student details, use$lookup.
Reviews: Reference (or Subset Pattern)
-
Reason: Thousands of reviews per course will quickly exceed MongoDB’s 16 MB document size limit. An array of thousands of review subdocuments will make the course document massive, causing performance issues on every read (even if you don’t need the reviews) and risking a write failure.
-
Model: Store reviews in a separate
reviewscollection with acourseIdreference. -
Optimization (Subset Pattern): If the UI needs to show the 5 most recent reviews on the course page, you can embed a small, bounded array of just those 5 “hot” reviews inside the course document, while keeping the full set in the separate collection. This avoids a
$lookupfor the common view while keeping the document small.
Summary:
-
Embed when the data is tightly coupled, bounded in size (a few dozen), and always read together.
-
Reference when the data is shared, large, unbounded, or updated independently.
-
-
Analytics Dashboard: MongoDB Aggregation Pipeline
Scenario: Generate a report showing total sales per category, top 5 products per category, and monthly revenue.
You can build this efficiently using a multi-stage aggregation pipeline that leverages
$facetto run multiple analytics sub-pipelines in parallel over the same input data, minimizing database scans.Pipeline Strategy:
-
$match: Filter to the relevant time period (e.g., the last year) to reduce the dataset size before processing. -
$facet: Create multiple sub-pipelines to calculate different metrics concurrently.-
Sub-pipeline A (Total Sales per Category):
$groupbycategoryand$sumthe sales. -
Sub-pipeline B (Top 5 Products per Category):
$sortby sales,$groupby category while using$pushor$sliceto keep only the top 5 products. Alternatively,$groupand then$topN(available in newer versions) within a$setWindowFieldsstage. -
Sub-pipeline C (Monthly Revenue):
$groupby month (using$monthand$yearon a date field) and$sumthe revenue.
-
Example Structure:
javascriptdb.orders.aggregate([ { $match: { status: "completed", orderDate: { $gte: ISODate("2025-01-01") } } }, { $facet: { "salesByCategory": [ { $unwind: "$items" }, { $group: { _id: "$items.category", totalSales: { $sum: "$items.price" } } }, { $sort: { totalSales: -1 } } ], "topProductsPerCategory": [ { $unwind: "$items" }, { $group: { _id: { category: "$items.category", product: "$items.productId" }, productSales: { $sum: "$items.price" } } }, { $sort: { "_id.category": 1, productSales: -1 } }, { $group: { _id: "$_id.category", topProducts: { $push: { product: "$_id.product", sales: "$productSales" } } } }, { $project: { topProducts: { $slice: ["$topProducts", 5] } } } ], "monthlyRevenue": [ { $group: { _id: { year: { $year: "$orderDate" }, month: { $month: "$orderDate" } }, revenue: { $sum: "$totalAmount" } } }, { $sort: { "_id.year": 1, "_id.month": 1 } } ] } } ])
Using
$facethere is highly efficient because MongoDB processes the initial$matchresults once and feeds them into all three sub-pipelines, rather than scanning the collection three separate times. -
-
Food Delivery App: Real-Time Order Updates
Scenario: Users need instant status updates when a restaurant accepts, prepares, or ships an order.
You should implement this using MongoDB Change Streams combined with Server-Sent Events (SSE) or WebSockets on the application side.
Implementation Steps:
-
Watch the Collection: On your Node.js (or other backend) server, open a Change Stream on the
orderscollection. You can use a$matchpipeline stage within the watch to only listen for updates to a specific order ID or for changes to thestatusfield, reducing unnecessary network traffic.javascriptconst changeStream = db.collection('orders').watch([ { $match: { "operationType": "update", "documentKey._id": orderId } } ]);
-
Handle Change Events: When the restaurant updates the order status in MongoDB (e.g., from “pending” to “preparing”), MongoDB pushes a change event to your application. The application server listens for this event.
-
Push to Client (SSE/WebSocket): Upon receiving the change event, your server immediately pushes the new status to the connected client (the user’s app) using a persistent connection like Server-Sent Events (SSE) or WebSockets. SSE is particularly well-suited for unidirectional server-to-client updates like this.
javascriptchangeStream.on("change", async (change) => { const updatedOrder = await db.collection('orders').findOne({ _id: orderId }); // Send the updated order data to the client via SSE res.write(`data: ${JSON.stringify(updatedOrder)}\n\n`); });
Why Change Streams?
Unlike polling (where the app repeatedly asks “any updates?”), Change Streams provide a reactive, push-based mechanism. The application is notified instantly when the data changes, enabling a real-time user experience with minimal latency and reduced database load. You also get built-in resilience; if your application disconnects, Change Streams support resuming from a specific point using a resume token. -
-
Optimizing Slow Email Queries on a 10-Million Document Collection
Problem Statement
Your MongoDB collection contains over 10 million documents, and queries that search users by their email field are very slow. What steps would you take to optimize query performance?
Step 1: Diagnose the Root Cause with
explain()The first step is to confirm why the query is slow. Use
explain("executionStats")to see the query plan:javascriptdb.users.find({ email: "[email protected]" }).explain("executionStats")
Look for the
winningPlan.stagefield:-
COLLSCAN— Collection scan (bad). MongoDB is reading every one of the 10 million documents. -
IXSCAN— Index scan (good). MongoDB is using an index to jump directly to matching documents.
Also check
totalDocsExaminedvs.nReturned. IftotalDocsExaminedequals the collection size (10 million) whilenReturnedis 1, you have a classic unindexed query problem.Step 2: Create a Single-Field Index on
emailIf the diagnosis confirms a collection scan, create an index on the
emailfield:javascriptdb.users.createIndex({ email: 1 })
This converts the query from a full collection scan to an index scan. For a lookup by a single, highly selective field like email, this is the single most impactful change you can make.
Email is an ideal candidate for indexing because it is:
-
Highly selective — each value filters out almost all documents.
-
Frequently queried — it is the primary lookup key for user authentication and profile retrieval.
Step 3: Consider a Covered Query
If your application only needs the
emailfield (and not the full user document), you can create a covered query that is satisfied entirely from the index, without fetching the document from disk:javascriptdb.users.find({ email: "[email protected]" }, { _id: 0, email: 1 })
For this to work, the index must include all queried fields. A covered query results in
totalDocsExamined: 0, which is extremely fast.Step 4: Use Projection to Avoid Fetching Unnecessary Fields
If you need the full document but the application only uses a subset of fields (e.g.,
nameandemail), add a projection:javascriptdb.users.find({ email: "[email protected]" }, { name: 1, email: 1 })
This reduces the amount of data transferred from disk and over the network.
Step 5: Verify Index Usage and Monitor
After creating the index, re-run
explain()to confirm the plan now showsIXSCAN. Use the database profiler to identify any other slow queries that may be performing collection scans:javascriptdb.setProfilingLevel(1, { slowms: 100 }) db.system.profile.find({ "planSummary": /COLLSCAN/ }).sort({ ts: -1 }).limit(10)
Production Considerations
-
Unique index: If email addresses must be unique, create the index with
{ unique: true }to enforce this at the database level. -
Write overhead: Every index adds overhead to insert and update operations. Since email is rarely changed, the write cost is minimal.
-
Index size: Ensure the index fits in RAM for optimal performance. Check with
db.users.stats().indexSizes.
-
-
MongoDB and the Database-per-Service Pattern
Problem Statement
A company is migrating from a monolithic application to microservices, and each service needs its own database. How would MongoDB support the Database-per-Service pattern, and how would it handle communication between services?
How MongoDB Supports Database-per-Service
MongoDB is well-suited for the Database-per-Service pattern because each microservice can have its own MongoDB database (or even its own MongoDB cluster). This ensures that no service can directly query another service’s data, preserving service autonomy and independent deployability.
Why this matters: If the User Service could query the Order Service’s MongoDB database directly, it would create tight coupling. The User Service would depend on the Order Service’s internal schema, making independent deployments impossible. Database-per-Service enforces boundaries at the data layer.
Patterns for Communication Between Services
Since services cannot share databases directly, they must communicate through well-defined interfaces. MongoDB supports several patterns:
Pattern 1: API Composition
The simplest approach: one service calls another service’s REST or gRPC API to retrieve the data it needs.
Example: The Order Service needs user profile data. It calls the User Service’s
GET /users/{id}endpoint rather than querying the User Service’s MongoDB database.Trade-off: Adds network latency from multiple hops, but preserves strict service boundaries. Best for occasional, read-heavy cross-service queries.
Pattern 2: Event-Driven Data Replication
When Service A frequently needs data from Service B, replicate only the fields it needs into Service A’s own MongoDB database.
How it works: Service B publishes events when its data changes. Service A subscribes to these events and maintains a local, read-optimized copy of the data it needs.
Example: The Notification Service needs user email addresses to send notifications. Instead of calling the User Service on every notification, it subscribes to
user.updatedevents and stores a local copy of{ userId, email }in its own database.Trade-off: Data is eventually consistent, but reads are fast and local. Best for frequent cross-service data needs.
Pattern 3: Shared Read Model (CQRS)
For complex cross-service queries, maintain a dedicated read model database that aggregates data from multiple services.
How it works: Write services publish events. A read model service subscribes to these events and builds denormalized documents optimized for queries.
Example: An analytics dashboard needs data from Order, User, and Product services. A read model service consumes events from all three and builds a denormalized
dashboard_datacollection.Trade-off: Adds complexity but enables fast, complex queries across service boundaries.
Pattern 4: MongoDB Change Streams as Event Bus
MongoDB Change Streams can be used to automatically detect data changes in a service’s database and push them to a message broker (like RabbitMQ or Kafka).
How it works: The publishing service opens a Change Stream on its collection. When data changes, the Change Stream fires an event, which the service publishes to the message broker. Other services subscribe to relevant topics.
Example: The Course Service publishes
enrollment.createdevents when a student enrolls. The Notification Service consumes these events to create notifications.Choosing the Right Pattern
Scenario Recommended Pattern Occasional cross-service read API Composition Frequent read of another service’s data Event-Driven Replication Complex cross-service reporting Shared Read Model Real-time data propagation Change Streams Summary
MongoDB’s flexibility allows each microservice to own its database while still enabling communication through API composition, event-driven replication, shared read models, or Change Streams. The key principle is: never share databases directly; share data through interfaces
-
Using MongoDB Atlas Global Clusters for Global Performance
Problem Statement
A global application serves users in Asia, Europe, and North America. Users complain about slow database response times. How would you use MongoDB Atlas Global Clusters to improve performance and reduce latency?
Understanding the Problem
When an application is deployed globally but the database is hosted in a single region (e.g., North America), users in Asia and Europe experience high latency because every database request must travel across the globe. For example, a user in Singapore querying a database in Virginia, USA, faces a round-trip time of 200–250 ms — for every single query.
What Are Atlas Global Clusters?
Atlas Global Clusters use Zone Sharding to distribute data across geographic regions. Each region contains its own shard with a local primary, enabling low-latency reads and writes for users in that region.
How It Works
A Global Cluster supports up to nine zones. Each zone is associated with a geographic region and contains a shard (or shards) with a local primary. Atlas uses a location-aware shard key to route data to the correct zone based on the user’s location.
Key concepts:
-
Global Write Zones: Each zone has a “Highest Priority” region where the shard’s primary replica set member is deployed. Writes are routed to the primary of the zone corresponding to the user’s location.
-
Read-only Nodes in Other Regions: To enable low-latency reads of globally distributed data, Atlas deploys read-only nodes in other zones’ Highest Priority regions. A user in Europe can read data that primarily resides in Asia via a nearby read-only node, avoiding a cross-globe round trip.
-
Location-aware shard key: Atlas maps geographic locations to zones. When a document is inserted with a shard key containing a location value, it is written to the appropriate zone.
Implementation Steps
Step 1: Choose the Right Shard Key
The shard key must include a field that identifies the user’s geographic location (e.g.,
region: "apac",region: "emea",region: "amer"). This is the foundation of location-aware routing.Step 2: Configure Zones
In Atlas, define three zones (e.g.,
APAC,EMEA,AMER). For each zone, specify the cloud provider regions where the primary and secondary replica set members should be deployed.Step 3: Shard the Collection
Use the location field as part of the shard key. Atlas will automatically route documents to the correct zone based on the shard key value.
Step 4: Configure Application Routing
The application must include the location field in all queries and writes so that Atlas can route operations to the correct zone. For example, a user in Europe would have their requests tagged with
region: "emea", routing reads and writes to the European shard.Step 5: Enable Read-only Nodes for Global Reads
To allow users in one region to read data that primarily resides in another region with low latency, configure read-only nodes in each zone’s Highest Priority region. These nodes replicate data from other shards, enabling local reads of global data.
Expected Performance Improvement
Scenario Latency (approx.) Single-region cluster (Virginia) accessed from Singapore 200–250 ms Global Cluster with local shard in Singapore 5–15 ms (local read/write) Global Cluster reading cross-region data via local read-only node 20–40 ms Alternative: Multi-Region Deployment (Simpler)
If Global Clusters are too complex for your needs, a simpler alternative is to deploy separate multi-region clusters in each geographic region (e.g., one cluster in each of APAC, EMEA, and AMER) and route users to the nearest cluster. This is often the preferred approach for data sovereignty compliance (e.g., GDPR), but it requires application-level routing logic.
When to Use Global Clusters
Use Atlas Global Clusters when you need:
-
A single global connection string.
-
Global aggregations across all shards.
-
The ability to read/write all data from any location while still having regional read/write optimization.
Summary
Atlas Global Clusters solve global latency by placing data (and its primary) close to the users who access it most. Zone Sharding routes writes to the correct region, and read-only nodes in other regions enable low-latency reads of globally distributed data. The result is a single logical database that feels local to users everywhere.
-
-
Automatic Session Data Expiration with TTL Indexes
Problem Statement
Your application stores temporary user session data that should automatically expire after 24 hours. How would you implement automatic document deletion in MongoDB without running manual cleanup jobs?
What Are TTL Indexes?
TTL (Time-To-Live) indexes are special single-field indexes that MongoDB uses to automatically remove documents after a certain amount of time or at a specific clock time. This is ideal for session data, logs, event data, and other information with a finite lifespan.
How TTL Indexes Work
MongoDB runs a background thread that reads the date values in the TTL index and removes expired documents. The expiration is based on the indexed field’s value, not the current time.
Step 1: Ensure Your Session Documents Have a Date Field
Each session document must have a field containing a BSON Date that represents when the document was created (or last updated):
javascript{ _id: ObjectId(), sessionId: "abc123", userId: ObjectId("..."), data: { ... }, createdAt: ISODate("2026-10-05T10:00:00Z") }
Step 2: Create the TTL Index
Create a TTL index on the
createdAtfield withexpireAfterSeconds: 86400(24 hours = 86,400 seconds):javascriptdb.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 86400 } )
Once created, MongoDB automatically deletes documents 24 hours after their
createdAtvalue.Step 3: Verify the TTL Index
Check the index exists:
javascriptdb.sessions.getIndexes()
The output should show the TTL index with
expireAfterSeconds: 86400.Using a Dynamic Expiration Field (Optional)
If you want different documents to expire at different times, you can set
expireAfterSeconds: 0and store the expiration time in the indexed field:javascriptdb.sessions.createIndex({ "expiresAt": 1 }, { expireAfterSeconds: 0 })
Then set
expiresAtto the exact time the document should be deleted:javascriptdb.sessions.insertOne({ sessionId: "abc123", expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours from now })
MongoDB will delete the document when
expiresAtis reached.Production Considerations
Performance during initial deployment: When you first create a TTL index on a collection with many documents that already qualify for deletion, MongoDB may delete a large number of documents at once, causing performance issues. The recommended approach is to create the index during off-hours or manually delete qualifying documents in batches first.
Changing
expireAfterSeconds: Use thecollModcommand to modify the TTL value. Note that reducing the value can make many documents eligible for immediate deletion, which may impact performance.javascriptdb.runCommand({ collMod: "sessions", index: { keyPattern: { createdAt: 1 }, expireAfterSeconds: 43200 } })
Storage fragmentation: Deleting many documents can fragment storage files. If this becomes an issue, run the
compactcommand on the collection or perform an initial sync to reclaim space.Precision: TTL deletion is not instantaneous. There can be a delay of up to 60 seconds (or more under heavy load) between expiration and actual deletion. Applications should handle the possibility that an “expired” session may briefly still be readable.
Summary
TTL indexes provide a fully automatic, server-side mechanism for deleting session data after 24 hours. Create a single-field index on a date field with
expireAfterSeconds, and MongoDB handles the rest — no cron jobs, no manual cleanup, no application code required. - Integrating MongoDB with Apache Kafka for Real-Time Fraud Detection
Problem Statement
A fintech company needs to stream MongoDB data changes to an analytics platform using Apache Kafka for real-time fraud detection. How would you design an architecture that integrates MongoDB with Kafka?
Architecture Overview
text[MongoDB Transactions Collection] | | (Change Streams) v [MongoDB Kafka Source Connector] --> [Kafka Topics] | v [Stream Processing / Fraud Detection Engine] | v [Analytics Platform / Alerting System]Component 1: MongoDB Kafka Source Connector
The MongoDB Kafka Connector acts as a bridge between MongoDB and Kafka. The Source Connector captures changes from MongoDB collections and streams them into Kafka topics.
How it works: The connector uses MongoDB’s Change Streams to monitor changes in specified collections. When an insert, update, or delete occurs, the connector publishes the change event to a Kafka topic.
Configuration Example:
json{ "name": "mongodb-source-connector", "config": { "connector.class": "com.mongodb.kafka.connect.MongoSourceConnector", "connection.uri": "mongodb+srv://...", "database": "transactions", "collection": "payments", "pipeline": "[{\"$match\": {\"operationType\": {\"$in\": [\"insert\", \"update\"]}}}]", "topic.prefix": "fintech", "publish.full.document.only": "true" } }
Key settings:
-
pipeline: An aggregation pipeline that filters which changes the connector watches. You can filter by operation type, database, or collection name using$matchand$regex. For fraud detection, you typically want to capture inserts (new transactions) and updates (status changes). -
publish.full.document.only: When set totrue, the connector publishes only the full document, not the change stream metadata, simplifying downstream processing.
Component 2: Kafka Topics
Changes are published to Kafka topics. For fraud detection, you might use:
-
transactions.payments— all new payment transactions. -
transactions.updates— status changes (e.g., refunds, chargebacks).
The
topic.prefixsetting in the connector determines the topic naming convention.Component 3: Stream Processing / Fraud Detection Engine
A stream processing engine (Apache Flink, Kafka Streams, Spark Streaming) consumes from the Kafka topics and applies fraud detection rules in real time:
-
Velocity checks: More than N transactions from the same user in M minutes.
-
Geographic anomalies: Transaction from a location inconsistent with the user’s history.
-
Amount thresholds: Transactions above a dynamic threshold based on user behavior.
-
Pattern detection: Multiple small transactions followed by a large one.
Component 4: Analytics Platform and Alerting
Detected fraud events are written to an analytics platform (e.g., ClickHouse, Elasticsearch, or another MongoDB collection) for investigation. Alerts are sent to a fraud operations team.
Handling Multiple Databases and Collections
The source connector supports a
pipelinesetting that allows you to watch multiple databases or collections using regular expressions:json{ "pipeline": "[{\"$match\": {\"ns.db\": {\"$regex\": \"/^(transactions|users)$/\"}}}]" }
This watches the
transactionsandusersdatabases, ignoring all others.Handling Delete Events
For fraud detection, delete events may be relevant (e.g., a user deleting transaction history). By default, the connector captures all operation types. Use the
pipelineto include or exclude specific operations.Reliability and Fault Tolerance
-
Change Stream resume tokens: The connector automatically manages resume tokens. If the connector restarts, it resumes from where it left off, ensuring no data loss.
-
Kafka offset management: The connector commits offsets to Kafka, providing at-least-once delivery semantics.
-
Dead Letter Queue: Configure the connector to send failed messages to a dead letter queue for later inspection.
Performance Considerations
-
Batching: The connector batches change events before publishing to Kafka, reducing overhead.
-
Partitioning: Kafka topics should be partitioned by a key relevant to fraud detection (e.g.,
userId) to ensure all events for a user go to the same partition for ordered processing. -
Compression: Enable compression on Kafka topics to reduce network bandwidth.
Summary
The MongoDB Kafka Source Connector provides a reliable, scalable way to stream MongoDB changes to Kafka for real-time fraud detection. By combining Change Streams (MongoDB’s native CDC) with Kafka’s distributed messaging, you get a pipeline that captures every transaction as it happens, processes it in real time, and triggers alerts when suspicious patterns emerge.
Summary Cheat Sheet
Question Core Solution Key MongoDB Feature 1. Slow email queries Index the email field createIndex({ email: 1 })2. Database-per-Service Communicate via APIs, events, or shared read models Change Streams, event-driven replication 3. Global latency Zone Sharding for local writes, read-only nodes for global reads Atlas Global Clusters 4. Session expiration TTL index on a date field expireAfterSeconds5. MongoDB → Kafka Source Connector with Change Streams MongoDB Kafka Connector -

