skip to Main Content

I’ve been creating a multi tenant app where I’ve been creating the database connections on the fly as soon as I resolve the tenant database connection string from the request that has just hit the server.

It’s working as expected, but the connections keeps adding up and never they are never getting disconnected.
From what I’ve been reading, it seems like the mongoose.connect manages the connections but the mongoose.createConnection doesn’t, I’m not sure if my undestanding is correct here.

I thought on creating my own connection pool with map in memory and use the connection from the map if it already exists in the map, but I’m not sure if this is a good approach.

Does anyone know if there is a npm connection pool package already built for this issue? Or any implementation ideas?

I also thought closing out each connection manually when the request lifecycle ends, but it will affect the performance if I have to connect and disconnect from mongo per each request, instead of using a connection pool.

Here is the part of the code I’m creating the connection, nothing special here because I’m always creating the connection.

// ... Resolve connection string from request
let tentantConn;
try {
  // One connection per tenant
  tentantConn = await mongoose.createConnection(
    decrypt(tenant.dbUrl),
    {
      useNewUrlParser: true,
      useUnifiedTopology: true
    });
}catch (e) {
  req.log.info({ message: `Unauthorized - Error connecting to tenant database: ${currentHostname}`, error: e.message });
  return reply.status(401).send({ message: `Unauthorized - Error connecting to tenant database: ${currentHostname}`, error: e.message });
}
// ...

2

Answers


  1. Chosen as BEST ANSWER

    Took me few days to be able to get back to this issue, but I was able to tweak my code and now the connection count on mongodb atlas seems to be stable. I'm not super happy to be using a global variable to fix this issue, but it is solving my issue for now.

    async function switchTenantConnection(aConnStr, aDbName, aAsyncOpenCallback){
      
      const hasConn = global.connectionPoolTest !== null;
    
      if(!hasConn){
        const tentantConn =  await getTenantConnectionFromEncryptStr(aConnStr);
    
        if(aAsyncOpenCallback){
          tentantConn.once('open', aAsyncOpenCallback);
        }
    
        tentantConn.once('disconnected', async function () {
          global.connectionPoolTest = null;
        });
    
        tentantConn.once('error', async function () {
          global.connectionPoolTest = null;
        });
    
        global.connectionPoolTest= { dbName: aDbName, connection: tentantConn, createdAt: new Date() };
        return tentantConn;
      }  
    
      return global.connectionPoolTest.connection.useDb(aDbName);
    }
    

  2. The connection pool is implemented on the driver level:
    https://github.com/mongodb/node-mongodb-native/blob/main/src/cmap/connection_pool.ts

    By default it opens 5 connection per server. You can change pool size but you cannot disable it.

    Now, terminology is a bit confusing, as a single mongodb server / cluster can have multiple databases. They share the same connection string – same 5 connections from the pool regardless of number of databases.

    Assumption your tenants have individual clusters and do connect to different mongodb servers, in order to close these connections you need to explicitly call

    await mongoose.connection.close()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search