Multi-tenant application architecture with Node.js, Express, and Mongoose

Multi-tenancy is an architecture where a single instance of an application serves multiple customers or tenants. A tenant is a group of users who share a common access with a set of specific privileges to the application instance. With the help of multi-tenant architecture, we can provide each tenant with a shared instance of the infrastructure which includes computation time, database, access management, etc. As different tenants will be using the same instance of a service, the data schemas will have to follow a generic pattern.

So, the first question that arises is that, how do we segregate the incoming requests as per the tenants? If we find a way of separating the requests, we will be able to create a database connection for that tenant and use it for all the subsequent requests. This will ensure that data is stored on that tenant’s database only and service context can be restored for that specific tenant also.

We will use Express which is a node.js application framework that will provide a boilerplate for our demo application. MongoDB as the database. For this, I am assuming that you have a working MongoDB server (local/cloud).

Add alt text

1.

Create these two databases. In this example the tenants main database is eb392598-c595–44a0–961e-8c143503a37d and tenant config database is Tenants.

2.

After creating the databases above add this document to the tenants’ collection. Here, passwordSecret means the key that will be used while encrypting the password during registration. origin is the host address of your WebClient.

Add alt text

These are the properties that I have chosen for my JWT token payload. You can see tenentId property exists in the payload. We’ll see how have we utilized that later on.

3.

For exchanging a set of information we have to prepare some schemas e.g. tenantSchema, userSchema. Create a new file tenant.js and add these codes.

Add alt text

Create a new file user.js. Our database schemas are ready. Now, we have to create a database connection and exchange data in-between them. As we may have multiple tenants, we have to create a tenant database connection pool to save and reuse the connections later. If we don’t use a pool, each time the connection has to be remade which will slow down the throughput of our application. So, let’s make a connection pool.

4.

Create another file dbContext.js and add these codes. Note, if the signature of the token is valid you will extract the tenantId from the token and embed that onto the req object.

Add alt text

JWT token holds all the necessary information that we will be needing for authorization. Let’s decode the JWT token and extract the payload from the token. The payload contains a field tenantId.

Add alt text

Now, the key part is complete. We have successfully distinguished which tenant the request came from. Now, we just have to create the appropriate connection for that tenant and save that connection in the pool for future reference.

Add alt text

Finally, you have to add all these middlewares to enable multi-tenancy in your application. The sequence of the middleware matters. Sequence: verifyToken, dbContextAccessor, verifyUser.

5.

Here is an example of how to use the middlewares in your API.

That’s it… We’re done !!! 😀

N.B: This is my first article. Let me know if this helps and share your thoughts if you have any. Thank you for reading.