Skip to content

Node.js + MongoDB

MongoDB with Express and Next.js

Where the client lives in a server, and how a route handler should talk to a collection.

IntermediateAbout 6 minutes

The database client is a server object. It never ships to the browser. Route handlers call a small module that already has a connected client. They return JSON the UI can serialise — ObjectId becomes a string at the edge, not in React.

// db.js
export const client = new MongoClient(process.env.MONGO_URI);
export const users = client.db("app").collection("users");

// server.js
await client.connect();
app.get("/users/:id", async (req, res) => {
  const user = await users.findOne({ _id: new ObjectId(req.params.id) });
  if (!user) return res.status(404).end();
  res.json({ id: user._id.toString(), name: user.name, city: user.city });
});
Express — module-level client, handler stays thin
import { MongoClient } from "mongodb";

const uri = process.env.MONGO_URI;
const g = globalThis;

export const client = g._mongoClient ?? new MongoClient(uri);
if (process.env.NODE_ENV !== "production") g._mongoClient = client;

export const db = client.db("app");
// Use db only in Server Components, route handlers, server actions — never in client components.
Next.js — HMR and serverless both try to construct the module twice

Connect at process start in Express. In Next, first operation can lazy-connect; still one client. Do not import mongodb from a 'use client' file. Do not put MONGO_URI in NEXT_PUBLIC_*. Map documents in the handler so you do not leak passwordHash or a 2MB events array. This is not a full app architecture — it is where the socket lives.

Interview question

Where does MongoClient live in an Express or Next.js app?

Think about it first.