6

I'm researching a good way to implement multiple database for multi-tenant support using node.js + mongoose and mongodb.

I've found out that mongoose supports a method called createConnection() and I'm wondering the best practice to use that. Actually I am storing all of those connection in an array, separated by tenant. It'd be like:

var connections = [
   { tenant: 'TenantA', connection: mongoose.createConnection('tenant-a') },
   { tenant: 'TenantB', connection: mongoose.createConnection('tenant-b') }
];

Let's say the user send the tenant he will be logged in by request headers, and I get it in a very early middleware in express.

app.use(function (req, res, next) {
    req.mongoConnection = connections.find({tenant: req.get('tenant')});
});

The question is, is it OK to store those connections statically or a better move would be create that connection every time a request is made ?

Edit 2014-09-09 - More info on software requirements

At first we are going to have around 3 tenants, but our plan is to increase that number to 40 in a year or two. There are more read operations than write ones, it's basically a big data system with machine learning. It is not a freemium software. The databases are quite big because the amount of historical data, but it is not a problem to move very old data to another location (we already thought about that). We plan to shard it later if we run out of available resources on our database machine, we could also separate some tenants in different machines.

The thing that most intrigues me is that some people say it's not a good idea to have prefixed collections for multitenancy but the reasons for that are very short.

https://docs.compose.io/use-cases/multi-tenant.html

http://themongodba.wordpress.com/2014/04/20/building-fast-scalable-multi-tenant-apps-with-mongodb/

2
  • it's expensive to create and destroy connections all the time - are you using authentication in the DB? Or only in your application? Is each tenant in a separate instance, "db", separate "collection" or ...? i.e. how do connections differ? Commented Sep 5, 2014 at 16:45
  • Hey, thx for replying. The authentication happens on app level but it checks a mongo collection (users). The idea is to have a db for every tenant (after some research on the web, people say to avoid prefix collection but they don't say why...). We don't know yet how the tenants will differ from each other, maybe some time in the future, but I'd like to have it prepared for it like different indexes. Commented Sep 6, 2014 at 18:28

1 Answer 1

11

I would not recommend manually creating and managing those separate connections. I don't know the details of your multi-tenant requirements (number of tenants, size of databases, expected number transactions, etc), but I think it would be better to go with something like Mongoose's useDb function. Then Mongoose can handle all the connection pool details.

update

The first direction I would explore is to setup each tenant on a separate node process. There are some interesting benefits to running your tenants in separate node processes. It makes sense from a security standpoint (isolated memory) and from a stability standpoint (one tenant process crash doesn't effect others).

Assuming you're basing the tenancy off of the URL, you would setup a proxy server in front of the actual tenant servers. It's job would be to look at the URL and route to the correct process based on that information. This is a very straightforward node http proxy setup. Each tenant instance could be the exact same code base, but launched with a different config (which tells them what mongo connection string to use).

This means you're able to design your actual application as if it wasn't multi-tenant. Each process only knows about one mongo database, and there is no multi-tenant logic necessary. It also enables you to easily split up traffic later based on load. If you need split up the tenants for performance reasons, you can do it transparently at the proxy level. The DNS can all stay the same, and you can just move the server that the instances are on behind the scenes. You can even have the proxy balance the requests for a tenant between multiple servers.

Sign up to request clarification or add additional context in comments.

7 Comments

I have edited the question to provide more details on the requirements. As for the useDb Function, I thought it could be dangerous when a request is still running when a concurrent one reaches the server and change the database. If there is any operation left for the first request it could make changes on the wrong tenant. is that right ? Thx!
useDb returns another database object to operate off of. It will not change the existing database object, so no in flight operations will be applied to the wrong database.
Is the load going to be fairly consistent across tenants, or do you expect some tenants to have significantly higher usage / data requirements?
Updated above. I would lean towards pushing the tenancy logic to a proxy server, and designing the application itself as if it only had a single database to work with.
@TimothyStrimple I like your Idea, and i will like to run with it. Please can you demonostrate an example. And noob question, could i create a target programatically ? and if so, how would i do that if the targets info are stored in a db ? thanks
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.