2
votes

I saw a lot of posts and articles about this alert on MongoDB Atlas ("Connections % of configured limit has gone above 80"), but couldn't figure out how to solve it in my Next.js application.

I create my db connection outside the handler function. I used a middleware withDatabase.js:

const client = new MongoClient(process.env.MONGODB_URI, { 
    useNewUrlParser: true, 
    useUnifiedTopology: true 
});

const addDbToRequest = (handler, req, res) => {
    req.db = req.connection.db("MYDBNAME");
    return handler(req, res);
};

const withDatabase = handler => async (req, res) => {
    if (!client.isConnected()) {
        await client.connect();
    }
    req.connection = client;
    return addDbToRequest(handler, req, res);
};

export default withDatabase;

This middleware wraps the API endpoint handler.

Now, if I close the connection on every API handler when it finishes, like this:

    const { connection } = req;
    if (connection) {
        connection.close();
    }

Than, I'm getting an error on the second request to the same api handler:

MongoError: Topology is closed, please connect

And if i'm not closing the connection, i'm getting this alert (after a short time of use) to my email:

Connections % of configured limit has gone above 80

What is the best practices to work with MongoDB Atlas in a Next.js application?

Thanks!

2

2 Answers

3
votes

The connection should be reused for the following reasons:

  1. Opening and closing DB connections on every API request is slow.
  2. It's hardly scalable. Assuming you're making a few API requests simultaneously per user, you will reach the same connections limit quickly when the app gets more users.

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

Default MongoClient configuration has maximum number of connections per pool (poolSize) set to 5. So, you shouldn't see more than ~5 connections in MongoDB Atlas if you have only one app instance running and checking whether a client is connected already, like you do.

if (!client.isConnected()) {
  await client.connect();
}

Note, that Next.js "restarts" on every request in the development mode (next dev) and it seems it affects MongoClient cache and creates many connections. However in production mode, you shouldn't experience this issue.

0
votes

To fix the max connections reached issue in Next's dev mode, I found writing the reused/cached client object to the global Node object allowed it to persist between refreshes.

const MongoClient = require('mongodb').MongoClient;

async function useMongoClient() {
  if (!this.client) {
    this.client = await MongoClient.connect(process.env.MONGODB_URI, {
      useUnifiedTopology: true,
    });
  }

  return this.client;
}

module.exports = useMongoClient;