Using (and reusing) multiple mongoose database connections on express.js Using (and reusing) multiple mongoose database connections on express.js mongoose mongoose

Using (and reusing) multiple mongoose database connections on express.js


Is this approach is efficient? Are there any bottlenecks/pitfalls I'm missing?

This all seems generally correct to me

What about the model registering?

I agree with @narc88 that you don't need to register models in middleware.

For lack of a better term, I would use a factory pattern. This "factory function" would take in your sub-domain, or however you decide to detect tenants, and return a Models object. If a given middleware wants to use its available Models you just do

var Models = require(/* path to your Model factory */);...// later on inside a route, or wherevervar models = Models(req.sub/* or req.tenant ?? */);models.Project.find(...);

For an example "factory", excuse the copy/paste

var mongoose = require('mongoose');var fs = require('fs');var debug = require('debug')('app:middleware:registerModels');var models = [];var conns = [];var path = __dirname + '/../schemas';function factory(tenant) {    // if the connection is cached on the array, reuse it    if (conns[tenant]) {        debug('reusing connection', tenant, '...');    } else {        debug('creating new connection to', tenant, '...');        conns[tenant] = mongoose.createConnection('mongodb://localhost:27017/' + tenant);    }    if(models[tenant]) {        debug('reusing models');    } else {        var instanceModels = [];        var schemas = fs.readdirSync(path);        debug('registering models');        schemas.forEach(function(schema) {            var model = schema.split('.').shift();            instanceModels[model] = conns[tenant].model(model, require([path, schema].join('/')));        });        models[tenant] = instanceModels;    }    return models[tenant];}module.exports = factory;

Aside from potential (albeit probably small) performance gain, I think it also has the advantage of:

  • doesn't clutter up the request object as much
  • you don't have to worry as much about middleware ordering
  • allows more easily abstracting permissions for a given set of models, i.e. the models aren't sitting on the request for all middleware to see
  • This approach doesn't tie your models to http requests, so you might have flexibility to use the same factory in a job queue, or whatever.