[node.js] How do I manage MongoDB connections in a Node.js web application?

I'm using the node-mongodb-native driver with MongoDB to write a website.

I have some questions about how to manage connections:

  1. Is it enough using only one MongoDB connection for all requests? Are there any performance issues? If not, can I setup a global connection to use in the whole application?

  2. If not, is it good if I open a new connection when request arrives, and close it when handled the request? Is it expensive to open and close a connection?

  3. Should I use a global connection pool? I hear the driver has a native connection pool. Is it a good choice?

  4. If I use a connection pool, how many connections should be used?

  5. Are there other things I should notice?

The answer is


The primary committer to node-mongodb-native says:

You open do MongoClient.connect once when your app boots up and reuse the db object. It's not a singleton connection pool each .connect creates a new connection pool.

So, to answer your question directly, reuse the db object that results from MongoClient.connect(). This gives you pooling, and will provide a noticeable speed increase as compared with opening/closing connections on each db action.


Open a new connection when the Node.js application starts, and reuse the existing db connection object:

/server.js

import express from 'express';
import Promise from 'bluebird';
import logger from 'winston';
import { MongoClient } from 'mongodb';
import config from './config';
import usersRestApi from './api/users';

const app = express();

app.use('/api/users', usersRestApi);

app.get('/', (req, res) => {
  res.send('Hello World');
});

// Create a MongoDB connection pool and start the application
// after the database connection is ready
MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => {
  if (err) {
    logger.warn(`Failed to connect to the database. ${err.stack}`);
  }
  app.locals.db = db;
  app.listen(config.port, () => {
    logger.info(`Node.js app is listening at http://localhost:${config.port}`);
  });
});

/api/users.js

import { Router } from 'express';
import { ObjectID } from 'mongodb';

const router = new Router();

router.get('/:id', async (req, res, next) => {
  try {
    const db = req.app.locals.db;
    const id = new ObjectID(req.params.id);
    const user = await db.collection('user').findOne({ _id: id }, {
      email: 1,
      firstName: 1,
      lastName: 1
    });

    if (user) {
      user.id = req.params.id;
      res.send(user);
    } else {
      res.sendStatus(404);
    }
  } catch (err) {
    next(err);
  }
});

export default router;

Source: How to Open Database Connections in a Node.js/Express App


Here is some code that will manage your MongoDB connections.

var MongoClient = require('mongodb').MongoClient;
var url = require("../config.json")["MongoDBURL"]

var option = {
  db:{
    numberOfRetries : 5
  },
  server: {
    auto_reconnect: true,
    poolSize : 40,
    socketOptions: {
        connectTimeoutMS: 500
    }
  },
  replSet: {},
  mongos: {}
};

function MongoPool(){}

var p_db;

function initPool(cb){
  MongoClient.connect(url, option, function(err, db) {
    if (err) throw err;

    p_db = db;
    if(cb && typeof(cb) == 'function')
        cb(p_db);
  });
  return MongoPool;
}

MongoPool.initPool = initPool;

function getInstance(cb){
  if(!p_db){
    initPool(cb)
  }
  else{
    if(cb && typeof(cb) == 'function')
      cb(p_db);
  }
}
MongoPool.getInstance = getInstance;

module.exports = MongoPool;

When you start the server, call initPool

require("mongo-pool").initPool();

Then in any other module you can do the following:

var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
    // Query your MongoDB database.
});

This is based on MongoDB documentation. Take a look at it.


Manage mongo connection pools in a single self contained module. This approach provides two benefits. Firstly it keeps your code modular and easier to test. Secondly your not forced to mix your database connection up in your request object which is NOT the place for a database connection object. (Given the nature of JavaScript I would consider it highly dangerous to mix in anything to an object constructed by library code). So with that you only need to Consider a module that exports two methods. connect = () => Promise and get = () => dbConnectionObject.

With such a module you can firstly connect to the database

// runs in boot.js or what ever file your application starts with
const db = require('./myAwesomeDbModule');
db.connect()
    .then(() => console.log('database connected'))
    .then(() => bootMyApplication())
    .catch((e) => {
        console.error(e);
        // Always hard exit on a database connection error
        process.exit(1);
    });

When in flight your app can simply call get() when it needs a DB connection.

const db = require('./myAwesomeDbModule');
db.get().find(...)... // I have excluded code here to keep the example  simple

If you set up your db module in the same way as the following not only will you have a way to ensure that your application will not boot unless you have a database connection you also have a global way of accessing your database connection pool that will error if you have not got a connection.

// myAwesomeDbModule.js
let connection = null;

module.exports.connect = () => new Promise((resolve, reject) => {
    MongoClient.connect(url, option, function(err, db) {
        if (err) { reject(err); return; };
        resolve(db);
        connection = db;
    });
});

module.exports.get = () => {
    if(!connection) {
        throw new Error('Call connect first!');
    }

    return connection;
}

If you have Express.js, you can use express-mongo-db for caching and sharing the MongoDB connection between requests without a pool (since the accepted answer says it is the right way to share the connection).

If not - you can look at its source code and use it in another framework.


You should create a connection as service then reuse it when need.

// db.service.js
import { MongoClient } from "mongodb";
import database from "../config/database";

const dbService = {
  db: undefined,
  connect: callback => {
    MongoClient.connect(database.uri, function(err, data) {
      if (err) {
        MongoClient.close();
        callback(err);
      }
      dbService.db = data;
      console.log("Connected to database");
      callback(null);
    });
  }
};

export default dbService;

my App.js sample

// App Start
dbService.connect(err => {
  if (err) {
    console.log("Error: ", err);
    process.exit(1);
  }

  server.listen(config.port, () => {
    console.log(`Api runnning at ${config.port}`);
  });
});

and use it wherever you want with

import dbService from "db.service.js"
const db = dbService.db

I have been using generic-pool with redis connections in my app - I highly recommend it. Its generic and I definitely know it works with mysql so I don't think you'll have any problems with it and mongo

https://github.com/coopernurse/node-pool


I have implemented below code in my project to implement connection pooling in my code so it will create a minimum connection in my project and reuse available connection

/* Mongo.js*/

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/yourdatabasename"; 
var assert = require('assert');

var connection=[];
// Create the database connection
establishConnection = function(callback){

                MongoClient.connect(url, { poolSize: 10 },function(err, db) {
                    assert.equal(null, err);

                        connection = db
                        if(typeof callback === 'function' && callback())
                            callback(connection)

                    }

                )



}

function getconnection(){
    return connection
}

module.exports = {

    establishConnection:establishConnection,
    getconnection:getconnection
}

/*app.js*/
// establish one connection with all other routes will use.
var db = require('./routes/mongo')

db.establishConnection();

//you can also call with callback if you wanna create any collection at starting
/*
db.establishConnection(function(conn){
  conn.createCollection("collectionName", function(err, res) {
    if (err) throw err;
    console.log("Collection created!");
  });
};
*/

// anyother route.js

var db = require('./mongo')

router.get('/', function(req, res, next) {
    var connection = db.getconnection()
    res.send("Hello");

});

Best approach to implement connection pooling is you should create one global array variable which hold db name with connection object returned by MongoClient and then reuse that connection whenever you need to contact Database.

  1. In your Server.js define var global.dbconnections = [];

  2. Create a Service naming connectionService.js. It will have 2 methods getConnection and createConnection. So when user will call getConnection(), it will find detail in global connection variable and return connection details if already exists else it will call createConnection() and return connection Details.

  3. Call this service using db_name and it will return connection object if it already have else it will create new connection and return it to you.

Hope it helps :)

Here is the connectionService.js code:

var mongo = require('mongoskin');
var mongodb = require('mongodb');
var Q = require('q');
var service = {};
service.getConnection = getConnection ;
module.exports = service;

function getConnection(appDB){
    var deferred = Q.defer();
    var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB)

    if(connectionDetails){deferred.resolve(connectionDetails.connection);
    }else{createConnection(appDB).then(function(connectionDetails){
            deferred.resolve(connectionDetails);})
    }
    return deferred.promise;
}

function createConnection(appDB){
    var deferred = Q.defer();
    mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=> 
    {
        if(err) deferred.reject(err.name + ': ' + err.message);
        global.dbconnections.push({appDB: appDB,  connection: database});
        deferred.resolve(database);
    })
     return deferred.promise;
} 

If using express there is another more straightforward method, which is to utilise Express's built in feature to share data between routes and modules within your app. There is an object called app.locals. We can attach properties to it and access it from inside our routes. To use it, instantiate your mongo connection in your app.js file.

var app = express();

MongoClient.connect('mongodb://localhost:27017/')
.then(client =>{
  const db = client.db('your-db');
  const collection = db.collection('your-collection');
  app.locals.collection = collection;
});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // view engine setup
app.set('views', path.join(__dirname, 'views'));

This database connection, or indeed any other data you wish to share around the modules of you app can now be accessed within your routes with req.app.locals as below without the need for creating and requiring additional modules.

app.get('/', (req, res) => {
  const collection = req.app.locals.collection;
  collection.find({}).toArray()
  .then(response => res.status(200).json(response))
  .catch(error => console.error(error));
});

This method ensures that you have a database connection open for the duration of your app unless you choose to close it at any time. It's easily accessible with req.app.locals.your-collection and doesn't require creation of any additional modules.


mongodb.com -> new project -> new cluster -> new collection -> connect -> IP address: 0.0.0.0/0 & db cred -> connect your application -> copy connection string and paste in .env file of your node app and make sure to replace "" with the actual password for the user and also replace "/test" with your db name

create new file .env

CONNECTIONSTRING=x --> const client = new MongoClient(CONNECTIONSTRING) 
PORT=8080 
JWTSECRET=mysuper456secret123phrase

Questions with node.js tag:

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean` jwt check if token expired Using Environment Variables with Vue.js Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true Can not find module “@angular-devkit/build-angular” MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] MySQL 8.0 - Client does not support authentication protocol requested by server; consider upgrading MySQL client npx command not found await is only valid in async function What could cause an error related to npm not being able to find a file? No contents in my node_modules subfolder. Why is that? How to set bot's status Returning data from Axios API Error: EACCES: permission denied, access '/usr/local/lib/node_modules' ReferenceError: fetch is not defined ERROR in Cannot find module 'node-sass' Test process.env with Jest 'react-scripts' is not recognized as an internal or external command NPM Install Error:Unexpected end of JSON input while parsing near '...nt-webpack-plugin":"0' db.collection is not a function when using MongoClient v3.0 When I run `npm install`, it returns with `ERR! code EINTEGRITY` (npm 5.3.0) E: Unable to locate package npm How can the default node version be set using NVM? How to downgrade Node version How to solve npm install throwing fsevents warning on non-MAC OS? How to read file with async/await properly? Angular: Cannot Get / The difference between "require(x)" and "import x" Is there a way to force npm to generate package-lock.json? Angular - ng: command not found MongoError: connect ECONNREFUSED 127.0.0.1:27017 How can I use async/await at the top level? ERROR in ./node_modules/css-loader? Downgrade npm to an older version Node - was compiled against a different Node.js version using NODE_MODULE_VERSION 51 npm install Error: rollbackFailedOptional npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY How can I use an ES6 import in Node.js? Node.js: Python not found exception due to node-sass and node-gyp bash: npm: command not found? npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\Nuwanst\package.json' Laravel 5.4 ‘cross-env’ Is Not Recognized as an Internal or External Command

Questions with mongodb tag:

Server Discovery And Monitoring engine is deprecated Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Failed to start mongod.service: Unit mongod.service not found db.collection is not a function when using MongoClient v3.0 MongoError: connect ECONNREFUSED 127.0.0.1:27017 MongoDB: How To Delete All Records Of A Collection in MongoDB Shell? How to resolve Nodejs: Error: ENOENT: no such file or directory How to create a DB for MongoDB container on start up? 'Field required a bean of type that could not be found.' error spring restful API using mongodb MongoDB: exception in initAndListen: 20 Attempted to create a lock file on a read-only directory: /data/db, terminating MongoDB: Server has startup warnings ''Access control is not enabled for the database'' MongoDb shuts down with Code 100 Mongodb: failed to connect to server on first connect MongoDB what are the default user and password? MongoDB: How to find the exact version of installed MongoDB show dbs gives "Not Authorized to execute command" error How to join multiple collections with $lookup in mongodb $lookup on ObjectId's in an array How to enable authentication on MongoDB through Docker? How do you put an image file in a json object? Push items into mongo array via mongoose Mongoose: findOneAndUpdate doesn't return updated document mongodb how to get max value from collections mongoError: Topology was destroyed MongoDB Data directory /data/db not found String field value length in mongoDB Uninstall mongoDB from ubuntu how to convert string to numerical values in mongodb MongoDB vs Firebase How to convert a pymongo.cursor.Cursor into a dict? E: Unable to locate package mongodb-org How to export JSON from MongoDB using Robomongo Difference between MongoDB and Mongoose Cannot find module '../build/Release/bson'] code: 'MODULE_NOT_FOUND' } js-bson: Failed to load c++ bson extension, using pure JS version How to connect Robomongo to MongoDB Mongodb find() query : return only unique values (no duplicates) How can you remove all documents from a collection with Mongoose? Find duplicate records in MongoDB sudo service mongodb restart gives "unrecognized service error" in ubuntu 14.0.4 how can I connect to a remote mongo server from Mac OS terminal Mongodb: Failed to connect to 127.0.0.1:27017, reason: errno:10061 BadValue Invalid or no user locale set. Please ensure LANG and/or LC_* environment variables are set correctly Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused How to list all databases in the mongo shell? TransactionRequiredException Executing an update/delete query How to select a single field for all documents in a MongoDB collection? MongoDB Show all contents from all collections Connection refused to MongoDB errno 111

Questions with database-connection tag:

Server Discovery And Monitoring engine is deprecated phpMyAdmin on MySQL 8.0 How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? MySQL Error: : 'Access denied for user 'root'@'localhost' Warning about SSL connection when connecting to MySQL database Fatal error: Call to a member function query() on null How to list active connections on PostgreSQL? How connect Postgres to localhost server using pgAdmin on Ubuntu? Oracle SQL Developer: Failure - Test failed: The Network Adapter could not establish the connection? How to increase MySQL connections(max_connections)? PG::ConnectionBad - could not connect to server: Connection refused Creating a new database and new connection in Oracle SQL Developer How to use PHP to connect to sql server Why am I getting "Cannot Connect to Server - A network-related or instance-specific error"? A network-related or instance-specific error occurred while establishing a connection to SQL Server Cannot create a connection to data source Error (rsErrorOpeningConnection) in SSRS Connection failed: SQLState: '01000' SQL Server Error: 10061 Is there a timeout for idle PostgreSQL connections? Using SQL LOADER in Oracle to import CSV file How do I manage MongoDB connections in a Node.js web application? How to form a correct MySQL connection string? ExecuteReader requires an open and available Connection. The connection's current state is Connecting Enable tcp\ip remote connections to sql server express already installed database with code or script(query) Setting up PostgreSQL ODBC on Windows Where are SQL Server connection attempts logged? php, mysql - Too many connections to database error Pass connection string to code-first DbContext How to get detailed list of connections to database in sql server 2005? How do I find out my MySQL URL, host, port and username? Python Database connection Close mysql server port number What is the format for the PostgreSQL connection string / URL? How can I access Oracle from Python? A connection was successfully established with the server, but then an error occurred during the pre-login handshake MSSQL Error 'The underlying provider failed on Open' Closing database connections in Java What is the point of "Initial Catalog" in a SQL Server connection string? Connect to external server by using phpMyAdmin How to fix "The ConnectionString property has not been initialized" How to connect to SQL Server database from JavaScript in the browser? What does "exec sp_reset_connection" mean in Sql Server Profiler?

Questions with connection-pooling tag:

How do I manage MongoDB connections in a Node.js web application? Should I set max pool size in database connection string? What happens if I don't? Configure hibernate to connect to database via JNDI Datasource How to get detailed list of connections to database in sql server 2005? Efficient SQL test query or validation query that will work across all (or most) databases Entity Framework and Connection Pooling How to establish a connection pool in JDBC? Connection pooling options with JDBC: DBCP vs C3P0