We are now in a process of migrating our server-per-client architecture to a multi-tenancy architecture. Everything is in place except for one design issue we are having.

We are using a subdomain in order to determine what tenant it is and route it to the proper DB (it is DB-per-tenant).

Let's say we have a tenant class with the following fields:

  • Id
  • Subdomain
  • DB Connection string

The question is how to save the tenant's data, it sounds like a simple question, but the problem is that each service will need to access that tenants list, as it happens in each request it needs to be fast and reliable. Keep in mind, most services are not on the same machine. We thought about the following options and I'll appreciate getting your opinion (especially if it is based on your experience):

  1. JSON File - All the tenants will be saved in a JSON file. The advantage is that it is very simple and fast. But, as this file can't be accessed through all the services it makes it not relevant for us.
  2. API - We will have another service that will hold all the tenants and will expose REST/GRPC API for getting the tenants list. The problem with it is that will require making a request on each incoming request which will cause performance issues. Caching might be a problem as this is critical information.
  3. Slave Caching - We will have a centralized service that will hold all the tenant's information. We will also have on each service an API (and storage) for getting the Tenants list. On each Tenant creation or edit on the main service, it will update all the depending services. The problem here is that it adds more overhead as we will need to create the same API in all of the services and register them.
  4. Shared DB - One centralized service to manage all the tenants, but the tenant's table/DB will be exposed to all of the other services so they will be able to query it directly. The problem I see here is performance as that DB will be a buttle neck for our entire platform as every request will have to query it.
  5. Master caching - Each service will have its own tenants list. On a new request, it will look for the tenant, if it can't find it, it will look for it in the tenant's service and will add it to the local list. The problem here is on editing a tenant. We will probably need to update all the depending services and therefore it makes more sense to use the Slave-Caching approach.

Am I missing other ways?

Thanks in advance, Shaul

  • How did you solve this problem? I have the same situation. Another question, do all of your services endpoints have a tenant_id parameter? In other words, how did you get the information from the tenant inside a micro service? – Guilherme Ferreira Oct 16 '20 at 12:56

If I understood correctly, you need to propagate tenant_id(*) to most (all?) of your services, which will then convert that tenant_id into database access information (not quite sure from your question, whether it's the same db all services uses or different ones).

This case seems to be very similar to authentication (even though I got an impression your services just trust each other understanding of tenant_id).

As for the solution, even some kind of distributes key-value storage may help you. They are quite fast, so there will probably be no need even to cache the answers. Key-value databases can be arranges in high-availability clusters, so I do not believe they will even be the bottleneck of your architecture.

So either go with some scalable authentication and authorization solution or key-value storage, depending on how your system's internal security is arranged.

For some reason, you keep mentioning "getting tenants list". The whole list is not even needed per request, if key-value storage can lookup tenant info for specific tenant_id.

"but the tenant's table/DB will be exposed to all of the other services so they will be able to query it directly." - this sounds like you will not be satisfied with any solution, which involves having tenants list available to all services. It is also possible, that when request enters your system and tenant's info determined, further request propagation will use some kind of time-limited token, which will be the key for the information on the specific tenant (maybe, even in encrypted form). This way, services will have no chance even to enumerate domains, if that is your concern.

(*)I call it tenant_id, but it may be a subdomain or whatever is the natural id for the tenant, which can be established on entry (you are authenticating your tenants, right?)

  • Thanks! This is really helpfull. Regarding the tenant's list, I meant to just get a specific tenant data from some kind of storage. Regarding the authentication, I'm using JWT and the tenant id is embedded as a claim, I'm also using the issuer claim to prevent cross tenant access, I'm using IdentiyServer4 (Oauth 2 and open ID connect) so I'm covered. Do you have a recommendation for a distributed key-value storage that will be scalable and fast enough? Though I'm emphasis the Slave-Caching approach as I think it will provide the best performance. – Shaul Zuarets Oct 14 '19 at 7:17
  • Maybe, some benchmarking / stresstesting is needed there. I only played with memcached, redis, Riak, ... I do not even think you will need to have a cluster unless you do it for Facebook. – Roman Susi Oct 14 '19 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.