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.