# How to Connect MongoDB with Node.js: Best Practices and Production-Ready Approaches

> Connect MongoDB with Node.js using the official driver or Mongoose. Learn production-ready approaches for reliable backend applications including connection pooling and error handling.

- Repository: [Node.js/node](https://github.com/nodejs/node)
- Tags: best-practices
- Published: 2026-02-16

---

**Use the official `mongodb` driver or Mongoose ODM with SRV connection strings, letting Node.js's built-in DNS module handle automatic cluster discovery while configuring connection pooling and error handling for production reliability.**

To connect MongoDB with Node.js for backend applications, developers rely on the runtime's low-level networking primitives that power database drivers. While the `nodejs/node` repository does not ship a built-in MongoDB driver, it provides the DNS resolution, TLS, and TCP infrastructure that makes robust database connectivity possible. Understanding how Node.js handles `mongodb+srv` connection strings and connection pooling helps you build secure, scalable backends.

## How Node.js Enables MongoDB Connections

Node.js provides the foundational networking layer that MongoDB drivers use to communicate with database clusters. When you use a connection URI starting with `mongodb+srv://`, the driver delegates hostname resolution to Node.js's native DNS module.

### SRV Record Resolution in Node.js Core

The `mongodb+srv` protocol relies on DNS SRV records to discover all nodes in a MongoDB replica set without hardcoding individual hostnames. Node.js resolves the `_mongodb._tcp` subdomain through its `dns.resolveSrv` method.

According to the Node.js source code, the resolver returns an array of objects containing `name`, `port`, `priority`, and `weight` properties. The test file [[`test/parallel/test-dns-resolvesrv.js`](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js)](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js) demonstrates this behavior, showing exactly how the driver receives the structured data needed for load-balancing and failover logic.

## Recommended Workflow to Connect MongoDB with Node.js

Follow these seven steps to implement production-ready MongoDB connectivity in your Node.js backend.

### 1. Choose the Official Driver or an ODM

Install the official `mongodb` package for direct database access:

```bash
npm install mongodb

```

For schema validation and model-based development, use **Mongoose**:

```bash
npm install mongoose

```

The official driver is actively maintained and supports the latest MongoDB server features, including automatic SRV resolution through Node.js's built-in DNS functionality.

### 2. Use an SRV Connection String

Format your URI to enable automatic cluster discovery:

```

mongodb+srv://<username>:<password>@cluster0.example.net/<dbname>?retryWrites=true&w=majority

```

This format triggers Node.js's DNS resolver to look up the `_mongodb._tcp` SRV records, returning all replica set members without manual configuration.

### 3. Leverage the Native DNS Module for Custom Resolution

When building custom connection pools or testing private DNS setups, use Node.js's `dns` module directly. The core test [[`test-dns-resolvesrv.js`](https://github.com/nodejs/node/blob/main/test-dns-resolvesrv.js)](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js) illustrates how to parse SRV records manually:

```javascript
const dns = require('dns').promises;

async function resolveMongoSrv(domain) {
  const records = await dns.resolveSrv(`_mongodb._tcp.${domain}`);
  return records.map(r => ({
    host: r.name,
    port: r.port,
    priority: r.priority,
    weight: r.weight
  }));
}

```

### 4. Configure Connection Options

Set these options when constructing your `MongoClient`:

- **`useUnifiedTopology: true`** – Enables the new connection management engine
- **`maxPoolSize`** – Controls connection pooling (default is 5)
- **`retryWrites: true`** – Enables automatic retry of failed writes
- **`tls: true`** – Enforces encrypted connections

### 5. Handle Errors Gracefully

Implement event listeners for network disruptions:

```javascript
client.on('error', err => console.error('MongoDB connection error:', err));
client.on('close', () => console.log('MongoDB connection closed'));

```

Wrap database operations in `try/catch` blocks to handle timeouts and network partitions without crashing your Node.js process.

### 6. Close the Client on Shutdown

Always release resources when your application terminates:

```javascript
process.on('SIGINT', async () => {
  await client.close();
  process.exit(0);
});

```

This ensures TCP sockets are properly closed and prevents connection leaks.

### 7. Secure Credentials

Never commit connection strings to version control. Use environment variables:

```javascript
const uri = process.env.MONGODB_URI;

```

For production deployments, integrate with secret managers like AWS Secrets Manager or HashiCorp Vault.

## Code Examples: Connecting to MongoDB from Node.js

### Using the Official MongoDB Driver

This example demonstrates a complete connection lifecycle with error handling and graceful shutdown:

```javascript
const { MongoClient } = require('mongodb');

const uri = process.env.MONGODB_URI;

async function run() {
  const client = new MongoClient(uri, {
    useUnifiedTopology: true,
    maxPoolSize: 20,
    retryWrites: true,
    w: 'majority'
  });

  try {
    await client.connect();
    console.log('Connected to MongoDB cluster');
    
    const db = client.db('production');
    const collection = db.collection('users');
    
    const result = await collection.insertOne({ 
      name: 'Alice', 
      createdAt: new Date() 
    });
    
    console.log('Document inserted:', result.insertedId);
  } catch (err) {
    console.error('Database operation failed:', err);
  } finally {
    await client.close();
    console.log('Connection closed');
  }
}

run();

```

### Using Mongoose for Schema Management

Mongoose provides a higher-level abstraction with built-in validation and middleware:

```javascript
const mongoose = require('mongoose');

const uri = process.env.MONGODB_URI;

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, unique: true },
  createdAt: { type: Date, default: Date.now }
});

const User = mongoose.model('User', userSchema);

async function main() {
  try {
    await mongoose.connect(uri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      serverSelectionTimeoutMS: 5000
    });
    
    console.log('Mongoose connected to MongoDB');
    
    const user = await User.create({ 
      name: 'Bob', 
      email: 'bob@example.com' 
    });
    
    console.log('Created user:', user);
  } catch (err) {
    console.error('Mongoose error:', err);
  } finally {
    await mongoose.disconnect();
    console.log('Disconnected');
  }
}

main();

```

### Custom SRV Resolution with Node.js DNS

For advanced use cases requiring custom load-balancing logic, manually resolve SRV records using Node.js core functionality:

```javascript
const dns = require('dns').promises;

async function resolveMongoCluster(domain) {
  try {
    const records = await dns.resolveSrv(`_mongodb._tcp.${domain}`);
    
    // Sort by priority (lower is better) and weight for load balancing
    const sorted = records.sort((a, b) => {
      if (a.priority !== b.priority) return a.priority - b.priority;
      return b.weight - a.weight;
    });
    
    return sorted.map(r => ({
      host: r.name,
      port: r.port,
      priority: r.priority,
      weight: r.weight
    }));
  } catch (err) {
    console.error('SRV resolution failed:', err);
    throw err;
  }
}

// Example: Discover cluster members before connecting
resolveMongoCluster('cluster0.example.net')
  .then(hosts => console.log('Discovered hosts:', hosts))
  .catch(console.error);

```

## Key Node.js Source Files Supporting MongoDB Connectivity

Understanding the underlying Node.js implementation helps debug connection issues and optimize performance:

- **[[`test/parallel/test-dns-resolvesrv.js`](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js)](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js)** – Demonstrates how Node.js resolves `_mongodb._tcp` SRV records, returning objects with `name`, `port`, `priority`, and `weight` properties that drivers use for automatic cluster discovery.

- **[[`lib/dns.js`](https://github.com/nodejs/node/blob/main/lib/dns.js)](https://github.com/nodejs/node/blob/main/lib/dns.js)** – The core DNS module implementation that exposes `resolveSrv` and other lookup methods. MongoDB drivers rely on this module when parsing `mongodb+srv` connection strings.

- **[[`doc/contributing/maintaining/maintaining-single-executable-application-support.md`](https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-single-executable-application-support.md)](https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-single-executable-application-support.md)** – References the `boxednode` project, which demonstrates how MongoDB driver implementations can be bundled with single-executable Node.js builds for deployment scenarios.

## Summary

- **Use the official driver**: Install `mongodb` or `mongoose` to connect MongoDB with Node.js, leveraging Node's built-in networking stack.
- **Leverage SRV records**: Use `mongodb+srv` URIs to enable automatic cluster discovery via Node.js's DNS resolver, as demonstrated in [`test-dns-resolvesrv.js`](https://github.com/nodejs/node/blob/main/test-dns-resolvesrv.js).
- **Configure for production**: Set `useUnifiedTopology`, connection pooling, TLS encryption, and graceful error handling.
- **Secure credentials**: Always use environment variables for connection strings and close clients properly on shutdown to prevent connection leaks.

## Frequently Asked Questions

### What is the difference between the MongoDB driver and Mongoose?

The **official MongoDB driver** (`mongodb` on npm) provides a thin wrapper around the database protocol, giving you direct access to collections and documents. **Mongoose** is an Object Document Mapper (ODM) that adds schema validation, middleware hooks, and model-based abstraction layers on top of the official driver. Choose the native driver for maximum flexibility and performance; choose Mongoose when you need strict schema enforcement and rapid application development.

### How does Node.js resolve mongodb+srv connection strings?

When you provide a `mongodb+srv` URI, the MongoDB driver calls Node.js's `dns.resolveSrv` method to query DNS for `_mongodb._tcp` records. As shown in the Node.js test file [[`test-dns-resolvesrv.js`](https://github.com/nodejs/node/blob/main/test-dns-resolvesrv.js)](https://github.com/nodejs/node/blob/main/test/parallel/test-dns-resolvesrv.js), this returns an array of server objects containing `name`, `port`, `priority`, and `weight` properties. The driver uses this data to discover all replica set members automatically, eliminating the need to list individual hosts in your connection string.

### Should I use environment variables for MongoDB connection strings?

Yes, always store MongoDB connection URIs in environment variables or dedicated secret management systems like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault. Never hard-code credentials in source files, as this exposes sensitive authentication data in version control. In your Node.js application, access the URI via `process.env.MONGODB_URI` and validate that it exists before attempting to connect.

### What is the purpose of useUnifiedTopology in MongoDB connections?

`useUnifiedTopology` is a connection option that enables the MongoDB driver's new connection management engine, which provides unified handling of server discovery, monitoring, and selection across standalone, replica set, and sharded cluster deployments. When set to `true`, the driver uses a single, cohesive topology monitoring layer that improves reliability and performance. This option is essential for production applications using modern MongoDB deployments and should be paired with proper error handling and connection pooling configuration.