Photo by Yosuke Ota on Unsplash

On this page

This chapter follows A short history of MongoDB. The examples assume MongoDB Server 8.0.x, the Node.js driver 7.8.x, and Node.js 20+. Pin versions in your own projects and check the driver compatibility table when you upgrade the server.

Run MongoDB in Docker

For local development, the community server image is enough for CRUD, aggregation, and geospatial exercises in this series:

Terminal window
docker pull mongodb/mongodb-community-server:8.0-ubuntu2204
docker run --name mongo-dev -p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=dev \
-e MONGO_INITDB_ROOT_PASSWORD=devpass \
-d mongodb/mongodb-community-server:8.0-ubuntu2204

Verify with mongosh (install from MongoDB Download Center):

Terminal window
mongosh "mongodb://dev:devpass@localhost:27017/admin" --eval "db.runCommand({ ping: 1 })"

Create a free Atlas cluster

  1. Sign up at MongoDB Atlas.
  2. Create an M0 free cluster in a region close to you.
  3. Add a database user and note the username and password.
  4. Under Network Access, allow your IP (or 0.0.0.0/0 only for short-lived experiments).
  5. Copy the connection string from Connect → Drivers.

Install the Atlas CLI if you prefer terminal workflows (Atlas CLI docs):

Terminal window
curl -sSf https://fastdl.mongodb.org/mongocli/mongodb-atlas-cli_latest_linux_x86_64.tar.gz | tar -xz
# move atlas binary to your PATH, then:
atlas auth login
atlas clusters list

Atlas URIs look like mongodb+srv://USER:PASS@cluster0.example.mongodb.net/myApp?retryWrites=true&w=majority. The mongodb+srv form resolves replica set members from DNS; the driver handles TLS automatically.

Install the Node.js driver

In your TypeScript project:

Terminal window
pnpm add mongodb
pnpm add -D typescript @types/node

The mongodb package ships its own TypeScript types; you do not need @types/mongodb.

Connection string anatomy

Part Meaning
mongodb:// or mongodb+srv:// Protocol; SRV for Atlas-style DNS
user:pass@ Credentials (URL-encode special characters)
host:27017 Server or seed host
/myDb Default database name
?authSource=admin Database that holds the user (often admin for root)
&replicaSet=rs0 Required for some replica set connections

Store secrets in environment variables, not source control:

Terminal window
export MONGODB_URI="mongodb://dev:devpass@localhost:27017/myapp?authSource=admin"

A typed client module

Reuse one MongoClient per process. The driver pools connections internally.

src/db/client.ts
import { MongoClient, Db } from 'mongodb';
const uri = process.env.MONGODB_URI;
if (!uri) {
throw new Error('MONGODB_URI is not set');
}
const client = new MongoClient(uri, {
maxPoolSize: 20,
serverSelectionTimeoutMS: 5_000,
socketTimeoutMS: 45_000,
});
let connectPromise: Promise<MongoClient> | undefined;
export async function getClient(): Promise<MongoClient> {
if (!connectPromise) {
connectPromise = client.connect().then(() => client);
}
return connectPromise;
}
export async function getDb(name = process.env.MONGODB_DB ?? 'myapp'): Promise<Db> {
const c = await getClient();
return c.db(name);
}
export async function closeClient(): Promise<void> {
if (connectPromise) {
await client.close();
connectPromise = undefined;
}
}

Ping after connect in health checks:

src/db/health.ts
import { getClient } from './client.js';
export async function pingMongo(): Promise<boolean> {
const client = await getClient();
await client.db('admin').command({ ping: 1 });
return true;
}

Graceful shutdown

Register shutdown hooks so in-flight operations finish before the process exits:

src/main.ts
import { closeClient } from './db/client.js';
async function shutdown(signal: string) {
console.log(`Received ${signal}, closing MongoDB client`);
await closeClient();
process.exit(0);
}
process.on('SIGINT', () => void shutdown('SIGINT'));
process.on('SIGTERM', () => void shutdown('SIGTERM'));

Next: Authentication in MongoDB.

Search articles

Type a word to search published articles.

Open the search page