Skip to content

MongoDB Fundamentals

How Node.js Connects to MongoDB

Connection strings, one MongoClient, the pool, and why a new client per request is a bug.

BeginnerAbout 6 minutes

The driver lesson showed new MongoClient and findOne. This lesson is the connection itself: where the URI lives, what the client reuses, and the bug that shows up in every first Express app.

  1. 01Node.js application
  2. 02MongoDB driver
  3. 03MongoClient (one per process)
  4. 04Connection pool
  5. 05MongoDB server

The connection string

MONGO_URI=mongodb://localhost:27017/app
Local development. Put this in the environment, not in git.

mongodb:// is the protocol. localhost:27017 is host and default port. /app is the default database name. Atlas URIs look like mongodb+srv://cluster... and include credentials. Same MongoClient, different string. Read it from process.env.MONGO_URI. Never commit a password in source.

One client, a pool behind it

MongoClient opens a pool of sockets, not a single connection. Each query borrows a socket, uses it, gives it back. Creating a client is the expensive part (handshake, auth, pool setup). Running findOne on an existing client is cheap.

import { MongoClient } from "mongodb";

const uri = process.env.MONGO_URI;
if (!uri) throw new Error("MONGO_URI is not set");

const client = new MongoClient(uri);
await client.connect();

const users = client.db("app").collection("users");

// In a route handler — no new MongoClient here:
export async function getUser(email) {
  return users.findOne({ email });
}
Reuse this client in every handler. Connect once at startup.
app.get("/users/:email", async (req, res) => {
  const client = new MongoClient(process.env.MONGO_URI);
  await client.connect();
  const user = await client.db("app").collection("users")
    .findOne({ email: req.params.email });
  await client.close();
  res.json(user);
});
Wrong: a new client (and pool) on every request

The second snippet works on a laptop and falls over in production: handshake per request, pool created and destroyed, latency spikes, connection limits hit on the server. In a long-running Node process, create one client at startup. In serverless, cache the client on the module so warm invocations reuse it — the Next.js lesson later shows that pattern.

Interview question

Why shouldn't you create a new MongoDB connection for every API request?

Think about it first.

Interview question

Where should a MongoDB connection string live in a Node.js app?

Think about it first.