Deep Dive into Connection Pooling

As your application grows in functionality and/or usage, managing resources becomes increasingly important. Failure to properly utilize connection pooling is one major "gotcha" that we've seen greatly impact MongoDB performance and trip up developers of all levels.

Connection pools

Creating new authenticated connections to the database is expensive. So, instead of creating and destroying connections for each request to the database, you want to re-use existing connections as much as possible. This is where connection pooling comes in.

A Connection Pool is a cache of database connections maintained by your driver so that connections can be re-used when new connections to the database are required. When properly used, connection pools allow you to minimize the frequency and number of new connections to your database.

Connection churn

Used improperly however, or not at all, your application will likely open and close new database connections too often, resulting in what we call "connection churn". In a high-throughput application this can result in a constant flood of new connection requests to your database which will adversely affect the performance of your database and your application.

Opening too many connections

Alternately, although less common, is the problem of creating too many MongoClient objects that are never closed.  In this case, instead of churn, you get a steady increase in the number of connections to your database such that you have tens of thousands of connections open when your application could almost certainly do with far fewer. Since each connection takes RAM, you may find yourself wasting a good portion of your memory on connections which will also adversely affect your application's performance.

Although every application is different and the total number of connections to your database will greatly depend on how many client processes or application servers are connected, in our experience, any connection count greater than 1000 - 1500 connections should raise an eyebrow, and most of the time your application will require far fewer than that.

MongoClient and connection pooling

Most MongoDB language drivers implement the MongoClient class which, if used properly, will handle connection pooling for you automatically.

The syntax differs per language, but often you do something like this to create a new connection-pool-enabled client to your database:

mongoClient = new MongoClient(URI, connectionOptions);

Here the mongoClient object holds your connection pool, and will give your app connections as needed. You should strive to create this object once as your application initializes and re-use this object throughout your application to talk to your database. The most common connection pooling problem we see results from applications that create a MongoClient object way too often, sometimes on each database request. If you do this you will not be using your connection pool as each MongoClient object maintains a separate pool that is not being reused by your application.

Example with Node.js

Let's look at a concrete example using the Node.js driver.

Creating new connections to the database using the Node.js driver is done like this:

The syntax for using MongoClient is slightly different here than with other drivers given Node's single-threaded nature, but the concept is the same. You only want to call 'connect' once during your apps initialization phase vs. on each database request.

Let's take a closer look at the difference between doing the right thing vs. doing the wrong thing.

Note: If you clone the repo from here, the logger will output your logs in your console so you can follow along.

Consider the following examples:

The first (no pooling):

  • calls connect() in every request handler
  • establishes new connections for every request (connection churn)
  • initializes the app (app.listen()) before database connections are made

The second (with pooling):

  • calls connect() once
  • reuses the database/collection variable (reuses existing connections) waits to initialize the app until after the database connection is established

If you run the first example and refresh your browser enough times, you'll quickly see that your MongoDB has a hard time handling the flood of connections and will terminate.

Further consideration - connection pool size

Most MongoDB drivers support a parameter that sets the max number of connections (pool size) available to your application. The connection pool size can be thought of as the max number of concurrent requests that your driver can service. The default pool size varies from driver to driver, e.g. for Node it is 5, whereas for Python it is 100. If you anticipate your application receiving many concurrent or long-running requests, we recommend increasing your pool size- adjust accordingly!

, , , , , ,

34 Responses to Deep Dive into Connection Pooling

  1. IamStalker 2013/11/07 at 12:50 am #

    Thank you it’s a real nice example, I will defently going to implement it in my web apps

  2. Chris Chang 2013/11/07 at 10:22 am #

    Glad it helps, happy hacking!

  3. Chaim Krause 2013/11/27 at 8:33 am #

    My app.js file is starting to get crowded with all the routes. I want to modularize my routes and move them to files in a route directory. I haven’t figured out how to make the database connection available to the modules. How do you suggest I do that? Should I make a global variable or should I move the MongoClient code to a module and require it? Any suggestions would be appreciated.

    Thanks for the article.

  4. Chris Chang 2013/11/27 at 10:30 am #

    Good question. Either works, as they both would ensure that you’re only creating one MongoClient. For a smaller app, you can get by with a global variable. For larger apps, you’ll want to modularize.

    Keep in mind to initialize the app after the database connection is created. We’ve seen users encounter unexpected behavior when their app first boots up and tries to query the database before the connection is ready.

    Thanks for reading!

  5. Luke Boehning 2014/03/16 at 3:00 pm #

    Thanks for straightening this out for me. I had copied and pasted the connection examples from api at Mongo (, where the connection is made once for each route. I sent about 1000 post messages to a route and my Express app bogged down to a crawl. Finally, Mongo sent a message back to Node letting me it hand “ended the connection”. After hours of digging, I found this post.

    Would somebody correct that horrible example at #mongoclient-connect?

  6. Chris Chang 2014/03/17 at 9:54 am #

    Glad to hear this post helped, Luke. I’ll try to get in contact with some folks from the MongoDB team and see if we can replace that code.


  7. Abirami R 2014/04/21 at 3:17 am #

    This database connection is useful and easily understand how to connect with pooling

  8. Nicolas Dughetti 2014/04/29 at 7:29 am #

    I think the best way is this:

    var routes = require(‘./app/routes’);
    var express = require(‘express’);
    var MongoClient = require(‘mongodb’).MongoClient,

    var app = express();

    var MONGODB_URI = ‘mongo-uri’;

    MongoClient.connect(MONGODB_URI, function(err, database) {
    “use strict”;
    if(err) throw err;


    console.log(‘Listening on port 3000’);

  9. MongoLab 2014/04/29 at 10:07 am #

    Thanks for reading and your suggestion! There are many ways to handle connection pooling (some more elegant than others). Your suggestion is great!

  10. shaun lim 2014/06/07 at 9:29 pm #

    Both good and bad code snippets currently point to good.js

  11. Chris Chang 2014/06/08 at 1:39 pm #

    Hi Shaun,

    I’m not seeing what you’re describing, is it pointing to good.js in the blog post or once you click on the snippet?

  12. Tom Caflisch 2014/09/04 at 7:14 am #

    One downside to this is that if you have your project broken out into /routes which import /controllers, which import /daos, then you have to pass your database object from your controller to your dao method. It’s not good practice to pass your db object from a controller to a dao method as the controller shouldn’t need to know how your dao method gets data.

    For this very reason I created this module:

  13. Tom Caflisch 2014/09/04 at 7:15 am #

    Check out this module that I created for this very reason:

  14. Kanti Varanasi 2014/10/13 at 1:56 pm #

    Great post!

    I am using the C++ driver, I have an issue where the application forks multiple processes. Each process uses a ScopedDBConnection object which maintains a pool with unlimited number of connections. With a system wide limit of 1024 connections, this is getting exhausted pretty fast.

    I would like to limit the pool size to ~5 using the C++ driver. Any pointers?
    Optionally, can I set this on mongod as a parameter on the server?

  15. Kevin 2015/03/27 at 7:22 am #

    Great article, and great comments too. Thanks for simple factory class Tom Caflisch.

  16. supi 2015/04/05 at 9:52 am #

    the whole point behind having a pool is the reuse of cached DB connections so the statement “maintains a pool with unlimited number of connections” doesn’t make sense. Since unlimited connections runs against the concept of reusing of limited connections, there is something wrong with the initialising of ScopedDBConnection object. Maybe checking that could resolve the issue?

  17. Zohar Sabari 2015/08/31 at 11:12 pm #

    Thanks for good article (and replies!), I also have a few questions I couldn’t find answers for.

    1. I have 2 databases and I want to have 2 separate connection pools simultaneously, one for each.
    All your samples show how to use shared connections to both databases.
    can you show an example how to do that? the thing is that each connection is opened on the MongoClient variable, which is the same variable to both (var MongoClient = require(‘mongodb’).MongoClient), so I’m not sure if multiple connections can be opened on the same variable simultaneously.

    2. I’m using both mongoose and the native driver in the same app, they are both connecting to same server but each to a different database. I first require mongoose and then the native drive. Since eventually mongoose uses the native driver as its core, my question is if the later connection definitions does not override the former.

    3. paramter wtimeout in connection options having a value of 0, does it mean that it wil not wait at all ot wait for infinity? is it relevant in the case where write concern w value is 0 or -1 (my case)?


  18. filozofeq 2015/11/06 at 3:49 am #

    Thank you for nice article.
    In fact my test shows that running query inside callback function of connect runs about 0,5-1 second due to overhead with connecting. Switching to db cached we skip the most overhead, query itself takes milliseconds only.

    For me it looks like Node.js example shows single connection pooling, but the article above says about multiple connections pooling. For intensively used applications it is worth to try multiple connections pooling by own implementation or maybe from generic-pool resource to have more than single connection only.

  19. алик 2015/11/12 at 10:05 am #

    And with koa.js how to?

  20. thecity2 2016/01/13 at 4:48 pm #

    So happy to find this post. I need to implement this!

  21. Rohit Bishnoi 2016/01/18 at 2:28 am #

    I am using mongodb java driver. Is there any way by which I can get the count of connection in use from the connection pool.

  22. Chris Chang 2016/01/18 at 10:03 am #

    The mongod logs log every connection to the database, so you can use the logs to see how many connections are opened when your Java application connects to your database.

  23. jhyguyh 2016/01/20 at 3:57 am #

    Funny. How do you plan to break your app into modules then? Or you want to have all you possible business logic in one place in one file? It’s definitely not as good approach.

  24. Rachel 2016/02/15 at 9:21 am #

    does this implementation mean that you no longer need to use db.close()?

  25. Sunoj Vijayan 2016/03/07 at 3:10 pm #

    What if I have multiple collections?

  26. mLab 2016/03/07 at 4:49 pm #

    It depends on your use case, but it’s generally not advisable to explicitly call db.close().

  27. mLab 2016/03/07 at 4:52 pm #

    The same rules apply. You can grab any collection in the database once your connection is authenticated. The example above uses coll = db.collection(‘test’); but you can change the collection name to anything.

  28. Landon Silla 2016/05/17 at 5:27 pm #

    How can I view the size of the queue? For example, let’s say that I had a pool size of 10, and I issued 1000 difficult commands instantly. I would want to know that there are 990 commands queued up within the MongoClient object. I’ve combed the source code, but I can’t seem to find it. Can you point me in the right direction?

  29. Itay 2016/11/16 at 11:18 pm #


    I have a small question about connection pool and collection access.
    If my db has several collections and i holding single MongoClient (as suggested).
    how good it will work if some hits to my server will use 1 collection and some other?
    Will it be more efficient to save reference to the collections?
    How the pool works in such cases?


  1. MongoDB driver tips & tricks: Mongoid 3 - 2014/02/27

    […] lower numbers this behavior is fine but once you get into thousands of connections you need to use connection pooling, which Mongoid does not directly support. We’ve directed our users to this thread on the issue, […]

  2. mongo connection pooling | wolfhesse - 2014/03/07

    […] 2014-03-05 wolfhesse Leave a comment   example included […]

  3. mongodb – Mongo Scaling – Too Many Connections – Linear Horizontal Scaling with 100s of App Servers | Asking - 2015/09/17

    […] proxy to route traffic from port 80). Each http server connects to the local mongos process using connection pooling with a poolSize of 3. Pretty simple so […]

  4. Python:how can I release mongodb connections? – IT Sprite - 2015/11/08

    […] […]

  5. Deploy Your Own REST API in 30 Mins Using mLabs and Heroku - 2016/04/07

    […] want to use our database connection pool as often as possible to best manage our available resources. We initialize the db variable in the […]

Leave a Reply