How to connect MongoDB to Node.js (and to your hosting)

Install the mongodb package, create a single MongoClient with the connection string stored in an environment variable and reuse that client across your whole app. The driver opens the connection on its own at the first operation.

Updated 5 min read

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

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.

MONGODB_URIenvironment variableconnection stringNode.js processRequestRequestRequestMongoClientone per processconnectionpoolMongoDBserver
One MongoClient per process reads MONGODB_URI and reuses its connection pool across every request.

What do you need before you start?#

  • Node.js installed and a project with a package.json. To use import, add "type": "module" to package.json.
  • A reachable MongoDB server: local, at a provider or on database hosting.
  • That server's connection string, username and password.

Install the driver:

bash
npm install mongodb

What 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 /database part sets which database client.db() opens when you don't pass a name. Without it, credentials are checked against the admin database. If the user was created in another database, use the authSource option.
  • Options come as key=value pairs separated by &, for example tls=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/mydb

Recent Node.js versions load that file without an extra package, using the --env-file flag:

bash
node --env-file=.env index.js

How do you connect, insert and query documents?#

Create index.js:

javascript
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:

javascript
// db.js
import { MongoClient } from "mongodb";

const client = new MongoClient(process.env.MONGODB_URI);

export const db = client.db();
export { client };
javascript
// 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:27017

Causes, 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:

  1. 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.
  2. Download the certificate. TLS is mandatory and the client also presents the certificate: pass tls: true, tlsCAFile with the downloaded CA and tlsCertificateKeyFile with the .pem in the MongoClient options.
  3. Set MONGODB_URI as 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.
  4. Deploy your code with the same MongoClient from this guide, adding those TLS options. The squarecloud.app file 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

Learn more

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.

Next article'Too many connections': database connection pooling explained'Too many connections' means your database hit max_connections. Learn why it happens in MySQL and PostgreSQL, how to diagnose it, and how pooling fixes it.

More in Databases

See all 24 articles