MongoDB is a document database: instead of rows in fixed tables, it stores flexible, JSON-like documents. Mongoose is the Node.js library most developers use on top of it, adding schemas, validation and a friendlier API. This guide explains how MongoDB works, when to choose it over a relational database, the essential queries, and how to use Mongoose safely in a Node.js app.
MongoDB stores data as BSON documents in collections, with flexible schemas, built-in replication and horizontal scaling. Use it when your data is naturally nested and varies from record to record; for most business apps, PostgreSQL or MySQL is still the safer default. In Node.js, connect with Mongoose using async/await, define schemas with validation, and never expose MongoDB to the internet without authentication. MongoDB is not available from Domain India shared hosting; run it on a VPS.
1. What MongoDB is
A MongoDB database holds collections, and each collection holds documents. A document is a set of fields, and a field can hold text, numbers, dates, arrays or other documents:
{
"_id": "665f1c2e9b1e8a3d4c5b6a7f",
"name": "Asha Rao",
"email": "[email protected]",
"addresses": [
{ "type": "billing", "city": "Chennai", "pin": "600001" }
],
"createdAt": "2026-09-23T10:15:00Z"
}MongoDB stores documents as BSON, a binary form of JSON that adds types JSON lacks, such as dates, 64-bit integers, decimals and binary data. Every document gets a unique _id.
Its main strengths:
- Flexible schema: documents in one collection don't need identical fields.
- Rich queries and indexes, including compound, text and geospatial indexes.
- Aggregation pipeline for reports and transformations inside the database.
- Replica sets for high availability, and sharding to spread data across servers.
- Multi-document transactions on replica sets, when you need them.
2. MongoDB or a relational database?
| Question | MongoDB | PostgreSQL or MySQL |
|---|---|---|
| Data shape | Nested, varies per record | Tables with clear relationships |
| Schema | Flexible; enforce it in your app or with validation | Defined in the database |
| Relationships and joins | Possible ($lookup), but not its strength | Core strength |
| Transactions | Supported; design to need them rarely | Standard for everything |
| Scaling | Built-in sharding across servers | Usually scale up, then replicas |
| Good fits | Catalogues, content, event logs, IoT data | Billing, orders, accounting, most business apps |
Both are fast, reliable and mature. Pick MongoDB when documents really are the natural shape of your data, not only to avoid designing a schema. PostgreSQL's JSONB column covers many "flexible data" needs inside a relational database. For a fuller comparison, see Choosing between PostgreSQL, MySQL, SQLite and MongoDB.
3. Tools you will use
- mongosh: the MongoDB Shell, for queries and admin work from a terminal. It replaced the old
mongoshell, which was removed in MongoDB 6.0. - MongoDB Compass: the official desktop app for browsing data, building queries and checking indexes.
- Official drivers for Node.js, Python, PHP, Java and other languages.
Robo 3T, which many older guides recommend, is no longer maintained. Use Compass instead.
4. Essential queries
These work in mongosh and, with small changes, in the Node.js driver.
// Create
db.users.insertOne({ name: "Asha", email: "[email protected]", active: true });
db.users.insertMany([{ name: "Ravi" }, { name: "Meena" }]);
// Read
db.users.find({ active: true }).sort({ name: 1 }).limit(20);
db.users.findOne({ email: "[email protected]" });
// Update
db.users.updateOne({ email: "[email protected]" }, { $set: { active: false } });
db.users.updateMany({ active: false }, { $set: { status: "archived" } });
// Delete
db.users.deleteOne({ email: "[email protected]" });Indexes make queries fast. Create one for every field you filter or sort on often:
db.users.createIndex({ email: 1 }, { unique: true });
db.orders.createIndex({ customerId: 1, createdAt: -1 });Aggregation runs multi-step reports inside the database:
db.orders.aggregate([
{ $match: { status: "paid" } },
{ $group: { _id: "$customerId", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
]);Use explain("executionStats") on a slow query to see whether it uses an index.
5. Mongoose: schemas and models
Mongoose is an Object Document Mapper (ODM) for Node.js. It adds a schema layer, validation, middleware and helpers on top of the MongoDB driver. Install it with npm install mongoose.
// db.js
import mongoose from 'mongoose';
await mongoose.connect(process.env.MONGODB_URI);
mongoose.connection.on('error', (err) => {
console.error('MongoDB connection error:', err);
});Keep the connection string in an environment variable, never in your code. Older guides pass useNewUrlParser and useUnifiedTopology; current Mongoose ignores them, so leave them out.
A schema with validation, and a model built from it:
import mongoose from 'mongoose';
import bcrypt from 'bcrypt';
const userSchema = new mongoose.Schema(
{
name: { type: String, required: true, trim: true },
email: { type: String, required: true, unique: true, lowercase: true },
passwordHash: { type: String, required: true, select: false },
role: { type: String, enum: ['customer', 'admin'], default: 'customer' }
},
{ timestamps: true }
);
userSchema.pre('save', async function () {
if (this.isModified('passwordHash')) {
this.passwordHash = await bcrypt.hash(this.passwordHash, 12);
}
});
export const User = mongoose.model('User', userSchema);select: false keeps the password hash out of query results unless you ask for it, and timestamps adds createdAt and updatedAt.
6. CRUD with Mongoose
Mongoose uses promises; callbacks were removed in Mongoose 7, so use async/await:
const user = await User.create({ name: 'Asha', email: '[email protected]', passwordHash: 'secret' });
const found = await User.findById(user._id).lean();
const admins = await User.find({ role: 'admin' }).sort({ name: 1 }).limit(50);
await User.findByIdAndUpdate(user._id, { name: 'Asha Rao' }, { new: true, runValidators: true });
await User.findByIdAndDelete(user._id);Two habits that matter:
- Use
.lean()for read-only queries. It returns plain objects and is much faster. - Pass
runValidators: trueon updates, because Mongoose does not validate update queries by default.
Population replaces a stored ID with the referenced document:
const postSchema = new mongoose.Schema({
title: String,
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});
const Post = mongoose.model('Post', postSchema);
const posts = await Post.find().populate('author', 'name email');Population runs extra queries, so for data you always read together, embedding it in one document is often better.
7. Security essentials
Automated scanners find MongoDB servers open on port 27017 within hours, then copy and delete the data for ransom. Turn on authorization, keep the server bound to 127.0.0.1 or a private network, and reach it remotely through an SSH tunnel or a firewall rule that allows only your app server.
- Turn on access control with
security.authorization: enabledinmongod.conf, and give each app its own user with access to its own database only. - Use TLS for any connection that leaves the server.
- Never build queries from raw user input. An attacker can send
{ "$ne": null }instead of a password. Validate input types, and keep Mongoose'ssanitizeFilteroption in mind. - Back up with
mongodump, and test a restore.
8. Scaling: replica sets and sharding
A replica set is a group of MongoDB servers holding the same data. One is the primary; the others copy it and take over automatically if it fails. Use at least three members in production. Replica sets also enable transactions and change streams.
Sharding splits a large collection across several replica sets using a shard key. It adds real complexity, so most apps never need it: add indexes, a bigger server and a replica set first.
9. Running MongoDB with Domain India
- A Domain India VPS, where you install and manage MongoDB yourself with full root access
- Your Node.js app on the same VPS, connecting over 127.0.0.1
- Shared hosting (cPanel, DirectAdmin, Webuzo): there is no MongoDB server, and you can't install one
- Connecting from shared hosting to MongoDB Atlas: outgoing port 27017 is not allowed on our shared servers
- Shared hosting runs Node.js apps with MySQL. MongoDB is not available from shared hosting, so use MySQL there, or move the app.
- App Platform runs Node.js apps and includes a PostgreSQL database with every plan. It has no built-in MongoDB. If you plan to connect an app there to an external MongoDB service, test the connection from the app before you rely on it.
- VPS is self-managed with full root access, so you can install MongoDB and keep it private. Follow Installing MongoDB on a Domain India VPS.
- 1 vCPU
- 2 GB DDR4 RAM
- 64 GB NVMe SSD Storage
- 2 TB Monthly Bandwidth
- 512 MB RAM per app
- 1 vCPU
- 5 GB NVMe SSD
- PostgreSQL Database
What is the difference between MongoDB and Mongoose?
MongoDB is the database server that stores documents. Mongoose is a Node.js library that connects to MongoDB and adds schemas, validation, middleware and model methods on top of the official driver.
Is MongoDB better than MySQL?
Neither is better in general. MongoDB suits nested, varied data such as catalogues and event logs. MySQL and PostgreSQL suit data with clear relationships, such as orders, invoices and accounts, which covers most business apps.
Can I use MongoDB on Domain India shared hosting?
No. Shared hosting has no MongoDB server, and outgoing connections to port 27017, which MongoDB Atlas uses, are not allowed from our shared servers. Use MySQL on shared hosting, or run MongoDB on a VPS.
Do I still need useNewUrlParser and useUnifiedTopology?
No. Current versions of Mongoose and the MongoDB Node.js driver ignore these options. Call mongoose.connect with just your connection string.
Does MongoDB support transactions?
Yes. MongoDB supports multi-document ACID transactions on replica sets and sharded clusters. Single-document writes are always atomic, so a good document design needs transactions only rarely.
How do I secure a MongoDB server?
Turn on authorization, create a separate user for each app, keep the server bound to 127.0.0.1 or a private network, use TLS for remote connections, and back up regularly with mongodump.
Ready to run MongoDB? Set it up on a Domain India VPS, or build your Node.js app on the App Platform with its included PostgreSQL database.
Full root access, so you can install MongoDB, keep it private and run your Node.js app beside it.
See VPS plans