How to approach a multitenant architecture solution?

I am currently asking myself what would be the best solution when it comes to a SaaS and the implementation of the multitenant part of it.

Either use infrastructure or do it at the code level.

For example,

I am currently working on some Identity and Access Management system and I get stuck in the dilemma of which solution to go for.

  1. Use the network infrastructure.
  2. Use database multitenant

What I mean with this is that I would normally spawn multiple servers and probably use some API gateway or subdomains or whatever that redirect the API calls to the correct server based on the business.

What I like about this is that I could maintain my code written as it was a singular business so details of which tenant I referring to goes away.

For example

We need to get some code or whatever to find the tenant.

tenant = find_the_tenant_somehow()

Accounts.create_account(tenant, user_params)

vs

We don’t need to pay attention to that because the server is running this code is for a single business.

Accounts.create_account(user_params)

This first example needs somehow a way to identify which business/tenant you are referring to, the second is you don’t need to pay attention to that.

I am not sure what would be the benefit of using multitenant and drive this logic at the code level since I never done this before.

Is there a better way?

I really would like to know your opinions about it and what do you recommend if you would use one of those packages as a dependency as well.

I guess in modern stacks is easier to spawn servers so we do not need to keep doing the old way to do things unless we definitely want the data to be shared but for these use cases is really rare so I am not concern about that.

Please leave your feedback.

1 Like

Spinning up multiple instances works alright if you have a limited number of tenants, but becomes increasingly wasteful as the number of tenants rises. Upgrades become increasingly more onerous as instead of upgrading the number of systems required to satisfy actual use and demand, you need to update one instance per tenant. It also means that every new tenant requires an update to the front-end proxies, and whenever a new tenant is added that either the sign-up/creation machinery needs to be able to influence the orchestration infrastructure (one more attack surface), or it requires manual intervention. (That last point is less important if tenants come on with a manual process on your part anyways.) Infrastructure management tools are pretty amazing these days, but there is no reason to be more wasteful or make life more complicated than necessary.

Another downside with multiple instances is that you now have 3 places to track your tenancy settings: the front-end proxies, the configuration on each deployment, and in your code. One may expect that putting the tenancy into config means removing all such considerations from you code … but should there be shared resources (e.g. common database tables / information) between tenants, then you end up having one path for tenant-specific resources and general resources. shrug

Multi-tenancy is not perfect, of course, but it is simpler to manage deployments for and allows easier sharing of common resources. It also does mean that per-tenant features can not be controlled by application-global configuration, but needs to be per-tenant … on the other hand that means all your tenant information is kept in one place (usually the database).

Tools like triplex makes tenancy easy, as well.

4 Likes

Basically all the issues that you commented here is the reason I am keep in the infinite loop about this.

I know how painful and unmanageable a non-multi-tenant platform could become but I think that the source code could become more tedious to work with.

What does AWS does? Or something like https://www.onelogin.com/ and https://www.pingidentity.com/en.html

What would be your speculations about these systems?

Btw, I am trying to create these SaaS as OTP applications that you would normally use and plug into your system so code readability and simplicity matters for me, but, I wouldn’t trade off to do the right thing.

Perhaps start with a simple test project and see how it works in practice, and then you will have some data to base a decision off of.

With ecto and triplex, it’s an extra line per tenantized query and you can pick out the tenant id in a plug so that is done in exactly one place. Not a big deal, really.

Here’s a screencast you may be interested in:

7 Likes

For what it’s worth, the approach of setting a tenant_id on each table keeps things simple and scales well. From there, if you actually grow the database farther than a single instance you will be ready for Citus.

4 Likes

I’ve done both approaches for multitenant applications, because the situation differed in subtle ways:

  • How many tenants do you expect? If it’s only a couple of dozen, and each one pays you plenty of monies, then you should probably just do a manual onboarding process and have each tenant on their own separate instance of your app. It allows you to give each tenant their own update schedule, means you never need to worry about them stomping all over each other, and can just generally babysit each customer as much as they deserve. On the other hand, if you expect thousands of tennants that don’t pay you very much, then you should do as much colocating as possible.

  • How much overlap do you expect them to have? If it makes business sense to give all your users a single account throughout your system, then you definitely don’t want to mess with SSO solutions right out the gate. That’ll cancel out the “simplicity” you would’ve otherwise had.

  • Do you expect your users to do local installations of your app? Worse, do you expect them to locally install the app and then have the app turn around and phone the mothership? If so, you might as well have all the hosted tenants on separate infrastructure behind an API gateway, so that the “cloud service” and the “on-prem service” can be kept as similar as possible.

By the way, if you get the choice wrong, you can fix it later. Slack started with all the tenants on separate VMs, but merged them into a single database later. Aspects of their UX still kind of reflect the old way, but it works and they’re doing fine overall despite the pivot.


You might notice that most of these aren’t really technical considerations, they’re business decisions. You need to decide if you want lots of cheap users, a self-serve web app, and not much integration, or if you want to go the Enterprise-with-a-capital-E path where your tenants each work with a sales representative (if this is a new company, that “sales rep” will probably be the same person as the CEO) and might get custom modules because one tenant asked for it.

6 Likes