Eshoponcontainers: [QUESTION] Multi-tenant solution

Created on 1 Feb 2018  Â·  6Comments  Â·  Source: dotnet-architecture/eShopOnContainers

Is there an easy way to extend this project to a multi-tenant solution (multiple eShops)? I am asking since in a monolith solution I could easily transform it to use separate databases for each tenant/domain but with micro-services I guess you might need to implement this feature in every service?

question

Most helpful comment

@jwillmer - Since EF Core 2.0, you now have a pretty good foundational approach for multi-tenancy in Entity Framework Core 2.0 by using the new Global query filters to filter data vertically.
Don't make me wrong, it is not a full multi-tenancy system but just a foundational artifact that you can use in order to implement multi-tenancy by sharing databases and schemas across tenants in a very transparent way when querying.
Global query filters allows a vertical filter to be configured for an entity type. This filter then applies to all queries, including eager loading (i.e. Include()). I.e. you could filter by TenantID so you won’t need to specify the TenantID in every query you create in your code. It can make multi-tenancy “transparent” for most of your queries.
Basically, you can evolve/improve a multi-tenancy approach like this (https://docs.microsoft.com/en-us/azure/app-service-web/web-sites-dotnet-entity-framework-row-level-security) by extending it with the new Global query filters from EF Core 2.

These filters are defined in the EF Core model as in the following code:
protected override void OnModelCreating(ModelBuilder modelBuilder)

{
  modelBuilder.Entity()
  .HasQueryFilter(p => !p.IsDisabled &&
  p.TenantId == this.TenantId );
}

In regards ASP.NET Identity and multi-tenant, it doesn’t provide that feature out of the box, but you could use similar approaches than the ones below, and potentially you could also use the new EF 2 QueryFilter capability within the ASP.NET Identity model (I haven’t tried this possibility, though).
https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy
https://github.com/JSkimming/AspNet.Identity.EntityFramework.Multitenant

I hope it helps. :)

Btw, I want to clarify that multi-tenancy is out of the scope of the functionality of eShopOnContainers. It is a business feature we cannot afford in regards cost of development at this moment. Usually, multitenancy should be an upfront business requirement or it'll need a lot of code work/refactoring afterwards.

All 6 comments

Well, you could do the same thing you're suggesting for a monolith, and duplicate all of the services per tenant. But I don't recommend it. Adding tenant as a part of the domain model and passing it anywhere it's needed seems like the simplest approach. If one used GUID keys for products, users, etc. throughout then there would be limited need to pass the tenant ID since any given product could be uniquely identified without the tenant ID. However, if you're using integer IDs you would likely need to pass tenant ID around virtually everywhere, in which case it might make sense to expect it in the form of an HTTP Header to any API calls so that it doesn't clutter every method signature.

I would tend to think you would just redeploy the microservices again in another k8s cloud that way you could balance the scaling on a tenant by tenant basis. Plus the Front ends would probably have a different look and feel based on tenant.

Register each microservice as a base docker image then just pull to make the new deploy.

How about one database per tenant? Still each micro service will have it's own tables (and no access to the other tables). This way a tenant could be easily backed up.
Sending the tenant id in the header and using a global configuration (service) to lookup the associated settings might be a good solution for this.

You can also have one database per service per tenant, and the service can use the correct database based on tenant value. As always it depends on your needs and resources.

Just for the k8s deployment, you don't need to have a cluster per tenant: if scaling tenant-based is needed, you can deploy the app for each tenant (in the same cluster) and scale by app.

You can also have one database per service per tenant, and the service can use the correct database based on tenant value. As always it depends on your needs and resources.

This is a little bit that worries me. If I like to deploy the project in the cloud multiple databases will cost a lot - especially if you have multiple tenants. I only found an Oracle product that offers a solution for multiple databases.

@jwillmer - Since EF Core 2.0, you now have a pretty good foundational approach for multi-tenancy in Entity Framework Core 2.0 by using the new Global query filters to filter data vertically.
Don't make me wrong, it is not a full multi-tenancy system but just a foundational artifact that you can use in order to implement multi-tenancy by sharing databases and schemas across tenants in a very transparent way when querying.
Global query filters allows a vertical filter to be configured for an entity type. This filter then applies to all queries, including eager loading (i.e. Include()). I.e. you could filter by TenantID so you won’t need to specify the TenantID in every query you create in your code. It can make multi-tenancy “transparent” for most of your queries.
Basically, you can evolve/improve a multi-tenancy approach like this (https://docs.microsoft.com/en-us/azure/app-service-web/web-sites-dotnet-entity-framework-row-level-security) by extending it with the new Global query filters from EF Core 2.

These filters are defined in the EF Core model as in the following code:
protected override void OnModelCreating(ModelBuilder modelBuilder)

{
  modelBuilder.Entity()
  .HasQueryFilter(p => !p.IsDisabled &&
  p.TenantId == this.TenantId );
}

In regards ASP.NET Identity and multi-tenant, it doesn’t provide that feature out of the box, but you could use similar approaches than the ones below, and potentially you could also use the new EF 2 QueryFilter capability within the ASP.NET Identity model (I haven’t tried this possibility, though).
https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy
https://github.com/JSkimming/AspNet.Identity.EntityFramework.Multitenant

I hope it helps. :)

Btw, I want to clarify that multi-tenancy is out of the scope of the functionality of eShopOnContainers. It is a business feature we cannot afford in regards cost of development at this moment. Usually, multitenancy should be an upfront business requirement or it'll need a lot of code work/refactoring afterwards.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chhotalamansukh picture chhotalamansukh  Â·  4Comments

dgaspar picture dgaspar  Â·  4Comments

DavidNorena picture DavidNorena  Â·  4Comments

arindams621 picture arindams621  Â·  5Comments

rafsanulhasan picture rafsanulhasan  Â·  3Comments