Learning objectives
After reading this article you will be able to:
- Install the official driver and build the connection string correctly
- Connect, insert and query documents with a reusable MongoClient
- Diagnose the most common connection errors, such as timeouts and authentication failures
On this page
- What do you need before you start?
- What does a MongoDB connection string look like?
- How do you store the connection string safely?
- How do you connect, insert and query documents?
- How do you reuse the connection in an API or bot?
- What are the most common connection errors?
- How to do this on Square Cloud
- FAQs
Connecting MongoDB to Node.js takes only a few lines, but it is where beginners hit the errors that block them most: a password with a special character, a new client on every request, a connection string hardcoded in the source. The examples use the official mongodb driver with ESM and async/await.
If you don't know the document model yet, read what MongoDB is first. Here the focus is the connection and what changes when the database lives on a remote server.
What do you need before you start?#
- Node.js installed and a project with a
package.json. To useimport, add"type": "module"topackage.json. - A reachable MongoDB server: local, at a provider or on database hosting.
- That server's connection string, username and password.
Install the driver:
npm install mongodbWhat does a MongoDB connection string look like?#
The connection string tells the driver where the server is and how to authenticate. The standard format is:
mongodb://[username:password@]host[:port][/database][?options]- Without a port, the driver uses
27017. - The
/databasepart sets which databaseclient.db()opens when you don't pass a name. Without it, credentials are checked against theadmindatabase. If the user was created in another database, use theauthSourceoption. - Options come as
key=valuepairs separated by&, for exampletls=true. - There is also the
mongodb+srv://format, which looks up the server list through DNS and is common for provider clusters. Your provider tells you which format to use.
Reserved characters in the username and password ($, :, /, ?, #, [, ], @) need percent-encoding. p@ss/word becomes p%40ss%2Fword. In Node.js, encodeURIComponent("p@ss/word") does the conversion.
How do you store the connection string safely?#
Never write the username and password in your code or push them to Git. Use an environment variable named, by convention, MONGODB_URI. To learn more, see what environment variables are.
Create a .env file (and add it to .gitignore):
MONGODB_URI=mongodb://user:password@host:27017/mydbRecent Node.js versions load that file without an extra package, using the --env-file flag:
node --env-file=.env index.jsHow do you connect, insert and query documents?#
Create index.js:
import { MongoClient } from "mongodb";
const uri = process.env.MONGODB_URI;
if (!uri) throw new Error("Set the MONGODB_URI variable");
const client = new MongoClient(uri);
async function main() {
await client.connect(); // optional, but fails early if something is wrong
const db = client.db(); // uses the database from the connection string
const users = db.collection("users");
await users.insertOne({ name: "Alice", createdAt: new Date() });
const alice = await users.findOne({ name: "Alice" });
console.log(alice);
}
main()
.catch((error) => {
console.error("Failed to use MongoDB:", error);
process.exitCode = 1;
})
.finally(() => client.close());Run it with node --env-file=.env index.js. If you see the document with an _id generated by MongoDB, the connection works. To check connectivity only, without writing anything, use await client.db("admin").command({ ping: 1 }).
In an API or bot that runs for a long time, don't call client.close() after every operation. That finally is there only because the script above exits on its own.
How do you reuse the connection in an API or bot?#
Each MongoClient keeps a connection pool, so create one per process and reuse it. Create the client in a module and import it wherever you need it:
// db.js
import { MongoClient } from "mongodb";
const client = new MongoClient(process.env.MONGODB_URI);
export const db = client.db();
export { client };// in any other file
import { db } from "./db.js";
const total = await db.collection("users").countDocuments();Because the driver connects at the first operation, you don't need await client.connect() here. The default maximum pool size is 100 connections (maxPoolSize); only change it if you have a measured reason. Creating a new client on every request or command wastes connections and slows everything down.
What are the most common connection errors?#
Server selection timeout. Example message, with the local database turned off:
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017Causes, from most to least common: the host in the string is wrong (for example localhost when the database is remote), the server is down, or a firewall blocks the port. Check the host and port first. You can shorten the wait with new MongoClient(uri, { serverSelectionTimeoutMS: 5000 }).
Authentication failure.
MongoServerError: Authentication failed.Check the username and password, the password's percent-encoding and authSource. A user created in the admin database needs ?authSource=admin in the string when the path points to another database.
TLS error. If the server requires an encrypted connection, add tls=true to the string. If it uses its own certificate, point the tlsCAFile option to the certificate authority file.
Empty variable. Without MONGODB_URI, the code above stops immediately with the message "Set the MONGODB_URI variable" in index.js. Run it with --env-file or check that the variable is defined in the environment.
Before you store real data, plan your database copies: see how to back up a database.
How to do this on Square Cloud#
Square Cloud offers MongoDB hosting starting on the Standard plan (Hobby doesn't include databases). The database is ready in seconds, in the same datacenter as your applications, with an average latency of about 1 ms. It is a single node (standalone, no replica set) and accepts up to 512 connections.
To connect your Node.js app:
- Create the MongoDB database in the dashboard (name and memory, from 1024 MB) and copy the full connection URL it gives you. It is shown only once, at creation; if you lose it, reset the password to see it again.
- Download the certificate. TLS is mandatory and the client also presents the certificate: pass
tls: true,tlsCAFilewith the downloaded CA andtlsCertificateKeyFilewith the.pemin theMongoClientoptions. - Set
MONGODB_URIas an environment variable of the application, in the dashboard, the API, the CLI or VS Code. The change applies on the next restart, without a rebuild. - Deploy your code with the same
MongoClientfrom this guide, adding those TLS options. Thesquarecloud.appfile is optional: the dashboard generates it during deploy, or you can write it at the project root.
The database also accepts connections from outside, so you can test the same URL and certificate on your own machine. You take manual snapshots whenever you want, and every plan that includes databases also has a daily automatic snapshot. You can restore a snapshot to the same database, to another one of the same engine or to a new database. More details on MongoDB hosting.
Database hosting
MongoDB, PostgreSQL, MySQL and Redis next to your app
FAQs
Do I need to call client.connect() before using the database?
No. Since version 4.7, the driver connects on its own at the first operation. Calling connect() explicitly only serves to confirm at startup that the connection works.
Should I create a MongoClient per request?
No. Each MongoClient keeps its own connection pool, so the recommendation is to create one per application and reuse it. The default maximum pool size is 100 connections (maxPoolSize).
Do I need Mongoose?
No. The official mongodb driver is enough to insert, query and aggregate. Mongoose is an optional layer that adds schemas and validation and uses the driver underneath.
My password has @ or / and the connection fails. What do I do?
Reserved characters in the username or password need percent-encoding in the connection string. For example, p@ss/word becomes p%40ss%2Fword. You can generate that with encodeURIComponent.
More in Databases
See all 24 articles- How much does database hosting cost?Cloud database hosting costs from zero to hundreds of dollars a month. See what sets the price: instance, disk, traffic, snapshots, and how to estimate yours.
- How to host a database for your appTo host a database, pick an engine, create the instance, store the connection string in an environment variable and test the connection. Step-by-step guide.
- What is Redis used for?Redis is an in-memory data store that keeps key-value pairs and rich data structures. Learn how it works, what it is used for and when not to use it.
- How to back up your databaseBack up MySQL, PostgreSQL and MongoDB with mysqldump, pg_dump and mongodump, then restore the dump. See the commands, how to verify and common mistakes.