Hello,
We have been working on a multi-tenant model for our business and using MongoDB for handling the data for our clients, our clients are basically some organizations that have their our users using the system.
Now we have a single application layer (single application deployment) for controlling or connecting to multiple databases within a single cluster. The change of database connection happens in the application (Built with Node.js and Mongoose) layer. Each database contains the same collections, for example db-00 and db-01 will have the same number of collections such as users, business_units, bookings, doucment_management, inventories… etc.
For each request entering the server the following code executes to connect the user request to the appropriate dataase:
const MONGO_URI = < only the cluster url with user and password no /db attached here >
let databaseCluster = {};
const connect = (db) => {
mongoose.plugin(forceRunValidators);
return mongoose.createConnection(
process.env.MONGO_URI + `/${db}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
autoIndex: true,
}
);
};
// this function si called once the server starts in the server js file
exports.connectToCluster = () =>
new Promise(async (resolve, reject) => {
try {
let adminConnection = await connect(process.env.ADMIN_DB);
let tenants = await Tetants(adminConnection).find({});
databaseCluster = adminConnection;
console.log("MongoDB admin Connected");
tenantsMap = tenants;
resolve("Tenants cached successfully.");
console.log("Tenants cached successfully");
} catch (err) {
console.error(err);
reject(err);
// Exit process with failure
process.exit(1);
}
});
exports.getConnectionByTenant = (tenantName) => {
let connection = null;
connection = databaseCluster.useDb(tenantName, { useCache: true });
return connection;
};
Whenever a model is compiled an example code looks like this:
const connection = getConnectionByTenant("my_tenant");
const ModelBuilder = (connection) => connection.model("collection_name",modelSchema);
const Model = ModelBuilder(connection);
Finally in the data access layer it is used as normal code as following:
// insert operation
const DataObject = new Model({
property_1:"some_value",
...
})
await dataObject.save();
// find operation
const data = await Model.findOne({});
The system works fine locally and Atlas cluster as well. It connects to different databases as expected. But we have come across a wired problem.
Problem statement
When inserting data only a single database becomes really slow, for example consider we have db_1, db_2, db_3 insert operation becomes really slow in db_3 even though there is almost no data and takes about 40 seconds to insert an item. And when we restart the server the problem shifts to a different database like db_2 and db_3 becomes normal. We have confirmed that this problem occurs on one database only doesn’t matter how may db we have. Except for the particular db all other dbs operate perfectly fine.
Could anyone help on this issue.
Reyads
Reyad