I have a Node.js project dealing with multiple customers. For several reasons, mainly separation of concerns, security, and partial transferability, I have to put every customer's data into a separate Mongo database. All databases store the same object types and thus have the same set of collections with identical structure. I have already found many technical solutions to solve that issue, but my question is more concerned with the best practices handling this situation. A simplified view into my code (omitting the boilerplate code to create a server, module structure, etc.):
const mongoose = require('mongoose');
// Customer codes act as DB names, actually comes from config file or DB
let customers = ['c1', 'c2'];
// keeps all mongoose connections
let conns = {};
// create a connection(pool) for each DB
for (let i in customers) {
let dbname = customers[i];
conns[dbname] = mongoose.createConnection(`mongodb://${host}:${port}/${dbname}`);
}
// a simple Schema for blog articles
const ArticleSchema = new mongoose.Schema({
title: String,
text: String
});
// keeps all Article models
let Article = {};
// create the identical models for the different DBs
// remember: the dbname is the unique customer's code
for (let dbname in conns) {
let conn = conns[dbname];
Article[dbname] = conn.model('Article', ArticleSchema);
}
const app = require('express');
// returns all articles of a certain customer
app.get('/customers/:customerid/articles', function(req, res) {
// get the customer's code from the URL
let dbname = req.params.customerid;
// Query the database
Article[dbname].find({}, function(err, articles) {
if (err) return res.status(500).send('DB error');
res.status(200).send(articles);
});
});
This code works. Nonetheless, I wonder, if there ist a best practice I am not aware of to handle this kind of requirement. Especially, it feels strange to keep the connections and models in maps and to access the objects with the dbname in square brackets. Please keep in mind that this is an extremely simplified version. In the real version the code is distributed across several modules handling different object types etc.
Note: A simple mongoose.connection.useDb(dbName) to switch to a different database doesn't work since the model has to be registered with respect to the connection, which itself must be bound to a database (as far as I understand it).
Update: Handling every customer with a single node process and setting up a proxy switching to those processes with respect to the customer - as suggested in the question mentioned by Paul - is currently not an option due to the administrative effort necessary to set things up in our current environment. We have to launch the service quickly right now.