EF Core Multitenancy For Your SaaS Applications

แชร์
ฝัง
  • เผยแพร่เมื่อ 15 ม.ค. 2025

ความคิดเห็น • 189

  • @MilanJovanovicTech
    @MilanJovanovicTech  11 หลายเดือนก่อน +25

    Get the source code for this video for FREE → the-dotnet-weekly.ck.page/multitenancy
    Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
    Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
    As a few awesome viewers have noted - the Tenant ID should come from a JWT or auth Cookie. I hoped that part was obvious since this is more of a proof of concept for Multitenancy. I wanted to focus on the EF features you can leverage to achieve this. And I left out the part about safely providing the Tenant ID. In any case, I'm updating this comment for posterity.
    TL;DR: For a production implementation, get the Tenant ID from the JWT/Cookie instead of passing it in a header.
    Join The .NET Weekly → bit.ly/4bfozSz
    It's a newsletter with 53,000+ engineers that teaches you how to improve at .NET and software architecture.

    • @JanKowalski-ld4ec
      @JanKowalski-ld4ec 11 หลายเดือนก่อน

      Great, just defined my question and sec later found the answer below (being already published ;)

    • @artfulperch
      @artfulperch 11 หลายเดือนก่อน

      Could it be a service behind the auth gateway, where the header value is assigned by a trusted service? Although a requirement to have the token with every request surely makes me feel more secure.

  • @d1ge
    @d1ge 11 หลายเดือนก่อน +9

    I never really found joy in backend development. After your videos about DDD, code architecture etc. Im finally enjoying writing backend code. Keep it going!

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +6

      I always found backend work much more enjoyable 😁

  • @Wickerman1989
    @Wickerman1989 11 หลายเดือนก่อน +2

    WOW. I recently had an interview about multitenancy, and I just popped these ideas out of my head - of course without implementation details.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Did you pass?

    • @Wickerman1989
      @Wickerman1989 11 หลายเดือนก่อน +2

      No, despite some good ideas I think they didn't want me due to lack of commercial experience with multi tenancy. Thanks for asking! @@MilanJovanovicTech

  • @juanlopeztello7315
    @juanlopeztello7315 11 หลายเดือนก่อน +12

    Adding a tenant_id claim inside a JWT is also a good option

    • @MaxSupercars
      @MaxSupercars 11 หลายเดือนก่อน +1

      It's better option. I have written comment to this also.

    • @randomic_bear
      @randomic_bear 11 หลายเดือนก่อน +3

      I'm actually implementing tenant_id instide the JWT token right now lol

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +3

      Right, I was sure I mentioned that in the video but sadly I didn't. Updating my pinned comment!

    • @fifty-plus
      @fifty-plus 11 หลายเดือนก่อน +1

      JWT is never a good option for general authn/authz despite it's popularity that all it's sprukers are trying to roll back now they know better.

  • @kodindoyannick5328
    @kodindoyannick5328 11 หลายเดือนก่อน +2

    Thank you Milan. You tought me again something new. Two weeks ago i enrolled in your Pragmatic Clean Architecture course after followed you on LinkedIn and TH-cam.

  • @Sqrlmasta
    @Sqrlmasta 11 หลายเดือนก่อน +4

    This is exactly how I implemented multi-tenancy in my last application, but like you said in your pinned comment, also passed in the tenantId from a JWT. In addition, instead of of adding a query filter on each modelBuilder, I added a global query filter that adds this to all my entities matching a base type I created for everything that would be tenant-specific

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Smart way to solve the query filter part!👌

    • @sushant-um6iv
      @sushant-um6iv 5 หลายเดือนก่อน

      Great idea!

  • @MaxSupercars
    @MaxSupercars 11 หลายเดือนก่อน +30

    Milan this is not usable, this is not the way how multitenancy will be implemented. Maybe if you would implement both sides: frontend and backend. But as soon as you make your backend API public, it's not possible that other side on frontend will be controlling access to data via custom HTTP header. It would mean that any user who can log-in could use any TenantId in header and access to data of other users/tenants. The better solution is to either have own AuthN server (or at least AuthZ function after external login) and return TenantId as a claim in a JWT token which is issued by the server side and can be verified and not modified by client. Second part of video - the connection string for tenants are normally saved for each tenant in the database and loaded for ex. once at login and stored in local browser storage. Also it's not needed to store TenantId for the records. Better solution is to store just CompanyId. Imagine that common function is to move company to other Tenant. In this case you just change the relation between CompanyId and other TenantId and you're good. You have to have function like "Check TenantId against Company" for controlling of access to data of different tenants.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +12

      I know, this is a 15-minute video, for crying out loud 😅 Did you expect me to give you a production-ready solution?
      If we just update the part for how we fetch the Tenant ID from a different source, everything else holds true.

    • @orlandomalo7032
      @orlandomalo7032 11 หลายเดือนก่อน

      What do you mean by "it's not needed to store TenantId for records", isn't it necessary to store the TenantId?

    • @MaxSupercars
      @MaxSupercars 11 หลายเดือนก่อน

      @@orlandomalo7032 As I have written. You store the records just with CompanyId. The relation between TenantId and CompanyId you got in a separate table and maybe database for fast access at the time of login/authentication.

    • @MaxSupercars
      @MaxSupercars 11 หลายเดือนก่อน +15

      @@MilanJovanovicTech Unfortunatelly it's very misleading and this solution gives the public the wrong way how to do it. In this case there is no difference between "home" and "production" version. Either it is done right or not right. And this is not. In 15 Minutes is possible to make the same video with other more secure solution like with JWT token etc.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +3

      @@MaxSupercars I think you and I have a different perspective of what a TH-cam video should convey

  • @JanKowalski-ld4ec
    @JanKowalski-ld4ec 11 หลายเดือนก่อน +1

    At last! Can't wait to watch on bigger screen! Thx!

  • @vasugupta1
    @vasugupta1 11 หลายเดือนก่อน +3

    I like your approach, but couldn't you create a DBContext Factory which returns you back a DBContext based on the tenantId you provided ?

  • @Dpaz2009
    @Dpaz2009 10 หลายเดือนก่อน +1

    That's a beautiful solution! Thanks for sharing!

  • @Dombling
    @Dombling 5 หลายเดือนก่อน +1

    Awesome video. It was what I needed in my project. Thank you !

  • @BlazorPlate
    @BlazorPlate 11 หลายเดือนก่อน +1

    Thank you so much for the informative video. Multitenancy, in general, is a bit challenging, especially when it comes to managing tenants and their subscriptions through a dedicated tenant administration portal. This is in conjunction with data isolation strategies such as a Shared Database for All Tenants and a Separate Database Per Tenant. We dedicated the past four years to analyzing and studying the best practices that should be considered when building a SaaS app using the Multitenancy approach.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +3

      Do you have these best practices categorized somewhere? :)

    • @BlazorPlate
      @BlazorPlate 11 หลายเดือนก่อน

      @@MilanJovanovicTech Yes, I do have :) I tried to post a long comment here but it gets removed automatically by YT algorithm due the restricted policy. Any workaround?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      @@BlazorPlate Try splitting the link like mywebsite . com

    • @BlazorPlate
      @BlazorPlate 11 หลายเดือนก่อน

      Thanks for the suggestion! Try without spaces :)
      docs. google. com/ document /d / 1cl37hdOfTLjVDo80gE5TPu7QDW5SZf1jQaLPH16k_Ig/ edit

    • @BlazorPlate
      @BlazorPlate 11 หลายเดือนก่อน

      @@MilanJovanovicTech Thanks for the suggestion. I also tried posting a comment as a link to google docs (with spaces) but I got caught!

  • @RMarjanovic
    @RMarjanovic 11 หลายเดือนก่อน +4

    I like the way you present the different tenant scenarios and how you automagically apply the tenantId in your queries. I didn't know you could use DI in the application DB context, to use values from an external service. Is this possible if using separate configuration files in combination with assembly scanning?
    I understand that you are only showing the basics in this video, but wondering if an improvement for a further video could be, using and validating JWT tokens. By accepting and reading the tenantId from the JWT token you protect against simply changing the tenantId in the header (if that's sensitive). You could just reference your video on JWT tokens in this video.

    • @matthewrossee
      @matthewrossee 11 หลายเดือนก่อน

      That's basically the same thing, except you're checking against the tenant's id in the token. When dealing with cookies, you can have different cookie schemas for each tenant.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +1

      | Is this possible if using separate configuration files in combination with assembly scanning?
      - It should be, what do you think would prevent this?
      I was sure I mention it in the video, but yes - the TenantId is more likely to live in a cookie or JWT.

    • @RMarjanovic
      @RMarjanovic 11 หลายเดือนก่อน

      @@MilanJovanovicTech well, when you say it, its the same functionality and process (ie per request handling) but getting it wired up is different, so you're pro'll right.

  • @antonmartyniuk
    @antonmartyniuk 11 หลายเดือนก่อน +1

    For the production app you need to check if a logged in user has access to a passed X-TenantId header. That way another user couldn't get data than doesn't belong to his tenant even if he somehow figures out the tenant identifier.
    This year my team was implementing a multi-tenant modular monolith application. We had some niche requirements where a user could have access to multiple tenants, single tenant or all tenants (i.e: super admin) defending on a role. It was the hardest use case of multi tenancy implemented by my lead

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Agreed, I noted in the comments that you should deal with the authentication aspect properly as I didn't cover that in this video

    • @holdenmoreland3119
      @holdenmoreland3119 5 หลายเดือนก่อน

      Doing this right now with my team. Would love some details on what y’all did. We have considered using the Claims table to identify membership/specific permissions for each tenant by including the tenantId in this table. A super admin claim with the tech support tenantId grants admin access to everything.

  • @randomic_bear
    @randomic_bear 11 หลายเดือนก่อน +2

    I wonder if we could apply the query filter by convention if the entity thas the TenantId field, then apply automagically, instead of adding the query filter to every single entity (or worse, the new intern forgetting to add the query filter to a new entity)

    • @juanlopeztello7315
      @juanlopeztello7315 11 หลายเดือนก่อน

      I saw something like that in stackoverflow if i'm not mistaken, it applied a configuration to all entities that implemented an interface, in this case could be something like ITenantModel

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      You can have your entities implement an interface, like ITenantId. The interface will have a single TenantId property.
      And then you should be able to say: modelBuilder.Entity().HasQueryFilter().
      *Don't take this as 100% true, I didn't check in my IDE. But that's the idea.

    • @MiningForPies
      @MiningForPies 11 หลายเดือนก่อน

      Be careful with query filters, they are not additive (well they weren’t before 8 I’ve not confirmed that yet).
      We had a filter like this to add the tenant id automatically to queries. But if you have another (in our case IDeletable) then the second filter replaces the first.

  • @truesoldier27
    @truesoldier27 11 หลายเดือนก่อน

    Do you have a video showing how you set up those logs to show in the docker window?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Just set the log level to Information

  • @batressc
    @batressc 6 หลายเดือนก่อน +1

    Always a good content quality! Thank you for sharing!

  • @alejandrasandoval5244
    @alejandrasandoval5244 11 หลายเดือนก่อน +1

    How to use this multitenancy using hangfire too?

  • @prathameshshende4
    @prathameshshende4 11 หลายเดือนก่อน +1

    Great video. How can I set the tenant id into the header after login or call login api ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      You'd store it in the JWT (instead of using a header)

  • @zeelove5535
    @zeelove5535 11 หลายเดือนก่อน +1

    can you teach completely how to use benchmarking with api projects .i love your videos.

  • @sunzhang-d9v
    @sunzhang-d9v 11 หลายเดือนก่อน +1

    I don't have a TenantId before logging in, how do I know which database to access?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      You'll get one assigned when logging in. The value will typically be set in a JWT or Cookie

  • @mmacrobert
    @mmacrobert 11 หลายเดือนก่อน +1

    Thanks for bringing clarity to this topic. Can you break down how to resolve tenants by using a sub-domain? Perhaps tenant-resolution is an abstraction in itself - perhaps by header, subdomain and even http-query-parameter.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      That'd be a topic for a different video

  • @sergius1298
    @sergius1298 11 หลายเดือนก่อน +1

    what if I got an unknown amount of tenants with same connection string but different database setting? How do I setup that one ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Place the "tenant-specific" tables into a custom schema, that could be one option

  • @PhantasyAI0
    @PhantasyAI0 10 หลายเดือนก่อน +1

    what about multi-tenant database per tenant? Meaning only the databases are whats separated they share the same web api. Its been hard to learn how to do this with ef core. My idea is ill have a master database to store all tenant info and connection strings. When a tenant signs up for example, ill create there database on azure. Use ef core, add them to the master database. When I need to connect to the tenant database, I query the master database, grab the connection string some how make ef core work with dynamic connection strings. Create maybe a initial setup, where you run the first migration (similar to update-database in package manager console) on the tenants database. However most of this is theory, would love a video on this.

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 หลายเดือนก่อน

      Well you've got a pretty good idea going there

  • @wendysanarwanto6817
    @wendysanarwanto6817 11 หลายเดือนก่อน

    Thank you for creating this helpful content, Milan ☺👏

  • @matthewrossee
    @matthewrossee 11 หลายเดือนก่อน +1

    How would you implement this if you wanted to allow the SaaS admin to also sign in to this application and perform some actions like inviting the company via email or issuing broadcast notification for all tenants? This would require a different entity than Company.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      You can have a different API for the admin that handles that, without any query filters

    • @matthewrossee
      @matthewrossee 11 หลายเดือนก่อน

      @@MilanJovanovicTech But then the second API for SaaS admin can't access tables in the first DB right? Is there any other way to do that in one api?

  • @mouradaissani8957
    @mouradaissani8957 11 หลายเดือนก่อน +1

    great video, thank you, what about multi-tenancy with single db and many schemas? (each schema ==> tenant)

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Similar to second scenario, except we'd configure the schema dynamically with HasSchema.
      Provisioning at the DB level is another headache.

  • @MiningForPies
    @MiningForPies 11 หลายเดือนก่อน +1

    We have a multi tenant system where some data is shared. We created them to be hierarchical so tenants can create their own sub tenants

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      That's cool. Do you still have everything in a single DB or are you running in a multi DB setup?

    • @MiningForPies
      @MiningForPies 11 หลายเดือนก่อน

      @@MilanJovanovicTech single db. The tenants are allocated to certain areas in the UK, but when a participant moves they will be transferred to a different tenant.
      A tenant can only view data that is linked to them, but they will get the data from the previous tenant to enable continuous service for the participant. (Project is in the criminal justice system so we get a lot of movement as people are transferred between and out of custody)

  • @Itfwf
    @Itfwf 11 หลายเดือนก่อน

    That’s the Microsoft docs, can you make a more realistic scenario? What about auth in these scenarios?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      That's a completely separate concern, IMO. It just comes down to how you fetch the Tenant ID value. Instead of getting it from a header, you'd fetch it form a JWT. Or use the User ID on the JWT to read the Tenant ID from the database. These are minor details in the overall scheme of things.

  • @subithsv
    @subithsv 7 หลายเดือนก่อน

    I have a question here. In DB per tenant model, how identity storage should be structured and implemented?

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +1

      Probably as a separate persistence store. But some applications will also require the users to be partitioned.

  • @ahmedtabba4891
    @ahmedtabba4891 11 หลายเดือนก่อน +1

    Love it ❤
    How to handle MIGRATIONS for multi DB scenario ❗️❗️

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Generate scripts, run them manually

    • @multistack
      @multistack 7 หลายเดือนก่อน

      @@MilanJovanovicTech How We will hadnle When Tenant Grows after 3 to 4 years of production, Code must be improve

  • @sunzhang-d9v
    @sunzhang-d9v 11 หลายเดือนก่อน

    Does TenantId need to be purchased? How to deal with it?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      It's just a way to identify a customer or group of users

  • @chuo129
    @chuo129 11 หลายเดือนก่อน +1

    YEEEEEEEEEEES, I've been struggling with this theme a few weeks ago. Thank you so much for this video. Hope you can continue it

  • @HXI-l8l
    @HXI-l8l 2 หลายเดือนก่อน

    That was a very useful video! Could you please post another one on implementing multi-tenancy using isolated databases for each tenant?

  • @orestpavlenko860
    @orestpavlenko860 10 หลายเดือนก่อน

    Hi. How i can setup individual users which does not have tenant?

  • @GunChen-v5x
    @GunChen-v5x 5 หลายเดือนก่อน

    Really useful, thanks, but in multiple database scenario, how to create a tenant ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 หลายเดือนก่อน

      We could have a dedicated tenant DB where we would first create a tenant, and then provision the required database

  • @christopherregula4610
    @christopherregula4610 11 หลายเดือนก่อน +1

    Great video!

  • @VicheaNath
    @VicheaNath 5 หลายเดือนก่อน

    What is base way to use with dapper

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 หลายเดือนก่อน

      Always include the tenant ID in the query

  • @alejomillo7744
    @alejomillo7744 7 หลายเดือนก่อน

    How you solve the Di of the service for running migrations? Since it throws a object null reference exception.

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน

      We can check if it's null and only add the query filter in the null case.
      Another option is using a different DbContext for migrations.

  • @emreteoman1564
    @emreteoman1564 11 หลายเดือนก่อน

    What is the best database migration strategy in case each tenant has different databases?

    • @drhdev
      @drhdev 11 หลายเดือนก่อน

      Different migrations

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      EF still works, but at some point it becomes smart to manage the DB migrations yourself.

  • @joyguan1476
    @joyguan1476 9 หลายเดือนก่อน

    Wouldn't data leak to another tenant if they changed the header value that holds the tenant id?

  • @daymaker_trading
    @daymaker_trading หลายเดือนก่อน

    THANK YOU so mcuh! Such a gem information!

  • @raocarry7734
    @raocarry7734 8 หลายเดือนก่อน

    I study a lot from your videos tks ,and I have a question how to change database connetctiongs when add a new tenant

  • @sunzhang-d9v
    @sunzhang-d9v 11 หลายเดือนก่อน

    Isn't it through TenantId that multiple databases determine which database to connect to? Before logging in, I don't know TenantId. How can I connect to the database and obtain user information? Is there a separate database for login logic?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      The identity service can live separately, yes. And after logging in you collect the required information.

  • @vano4ok
    @vano4ok 8 หลายเดือนก่อน

    Nice video. I have a question. How to make outbox pattern with separate databases? maybe job per tenant or something else

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 หลายเดือนก่อน

      Each DB would need its Outbox processor, I guess

  • @TheAzerue
    @TheAzerue 11 หลายเดือนก่อน

    I wondering how DbContextConnectionPool would work ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      It should work, in theory. Worth testing out the second scenario though 🤔

  • @sunzhang-d9v
    @sunzhang-d9v 11 หลายเดือนก่อน

    Logging in with a separate database?

  • @amirologi
    @amirologi 11 หลายเดือนก่อน

    Does anyone know the docs for creating a service? Please send the link.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      What do you mean by service?

    • @amirologi
      @amirologi 11 หลายเดือนก่อน

      @@MilanJovanovicTech I mean the provider: Services > TenantProvidor th-cam.com/video/Gf1sCvikpgI/w-d-xo.html

    • @amirologi
      @amirologi 11 หลายเดือนก่อน

      @@MilanJovanovicTech I mean the provider

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      @@amirologi www.milanjovanovic.tech/blog/multi-tenant-applications-with-ef-core

  • @vincentbenazet3137
    @vincentbenazet3137 5 หลายเดือนก่อน

    Hi Milan, thank you for your videos, they are great. I really like the part about filtering with EF Core, thanks :)
    I just have one point: I am not a big fan of doing the GetTenantId in the constructor because if there is an exception, it will be wrapped in a DI container exception (Autofac dependency injection exception).
    What do you think of the Finbuckle library for multi-tenant? I like it.

  • @andreituduce6127
    @andreituduce6127 11 หลายเดือนก่อน

    Hello,
    How would you do it if the connection strings would have to be dynamic as well for the single tenancy case?
    Ex: Company x and Company y both registered within the application and you have to build dynamic databases for both of them without modifying the current app.configuration file
    I also enjoy your content, keep it up!!
    Thank you!

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Have a set of migration SQL scripts that create the required database structure. Run it in the background when a company registers. Something along those lines.

  • @anandjaisy
    @anandjaisy 6 หลายเดือนก่อน

    @MilanJovanovicTech How about the schema based multi-tenant, I know it is not supported in EF core. Is there a way to do that ?

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 หลายเดือนก่อน

      I think it's possible with the HasDefaultSchema method

  • @jorgepedraza1275
    @jorgepedraza1275 11 หลายเดือนก่อน

    Excellent. As always, there is no free repository related to the video. Any sales channel through Amazon to buy your complete course🤔

  • @danvolovo5292
    @danvolovo5292 11 หลายเดือนก่อน +1

    Good episode 👍. It would be enlightening if you used a more realistic scenario, instead of headers, determined tenantId using custom claims extracted from JWT. An idea for a future episode.😉

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Didn't want to bother with JWTs/Auth, as I figured it would detract from the main point which is Multitenancy with EF

  • @MahmoudMouradSidky
    @MahmoudMouradSidky 6 หลายเดือนก่อน

    Thank you for the pro content

  • @banzeirao
    @banzeirao 6 หลายเดือนก่อน

    Ok but when generate efcore migrations with efcore tool: Unable to create a 'DbContext' of type ''. The exception 'Tenant ID not present'

  • @boyakoosha
    @boyakoosha 7 หลายเดือนก่อน

    Thanks for the effort, your videos are good and I appreciate the time like people yourself put into them. One question, in a Clean architecture with the core entities seperate from the main Infrastructure/Identity, what are people's view on creating entities that have relationships back to the individual user, rather than just the Tenant.
    For example, consider a "Keys" table maybe that is unique to the user logged in?

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +1

      I think it's fine, but wouldn't it still be scoped to a tenant also?

  • @CarlosCortes-dp1ci
    @CarlosCortes-dp1ci 7 หลายเดือนก่อน

    Hi Milan, I am a dedicated follower and student of your two courses. Do you have any plans for a course focused on multitenancy or SaaS applications? Any recommendations you could give me for my project? I would like to follow the strategy of using EF Core for commands and Dapper for queries. Additionally, I would like to use Keycloak as the identity provider for the different tenants. Thank you for your videos; they are very helpful for our projects and for improving as software architects.

    • @MilanJovanovicTech
      @MilanJovanovicTech  7 หลายเดือนก่อน +1

      Not in the recent future, no. I might do a longer video about multitenancy for YT

  • @Sanatani-k1s
    @Sanatani-k1s 9 หลายเดือนก่อน

    Will this resolves concurrency? As multiple concurrent tenants using at same time? e.g. in terms of lambda functions. I am new to this by the way..

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 หลายเดือนก่อน

      Wouldn't each lambda run inside its own context?

  • @CarCan316
    @CarCan316 6 หลายเดือนก่อน

    This may seem like a novice question, but if the SasS application is going to be used for multiple domain names, where each spins up its own instance of the application with its individual frontend, if anyone has an example of how to solve that issue, I'd be very interested to see how thats done.

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 หลายเดือนก่อน

      We should be able to figure out the tenant based on the domain name, I think Derek has a good video about that if you check out his channel

    • @CarCan316
      @CarCan316 6 หลายเดือนก่อน

      @@MilanJovanovicTech Thank you, Milan, that sounds exciting. If you can let me know what the channel name is or a link to it, that would be most helpful! Also, just wanted to say, your videos are pretty damned interesting, the subject matter you are choosing to cover is awesome. Thanks again!

  • @thanasakis61
    @thanasakis61 11 หลายเดือนก่อน

    Hi Milan, I would like to note here that the firtst approach with the EF Query Filters is applicable when your users or tenants exists outside of this application. For example I have an MVC asp net core application and users are inside the same application (monolith) which makes it a mutlitenant application since every user can only access and modify their own data and all of them exist in the same databse. However the approach with the app user resolver service did not work for me. THe reason is because the OnModelCreating method is only called once for the project's lifetime. So before anyone would login the query filters had alreaady instatiated with null as the tenantId. I was actually around this issue for some time but for this type of application i mentioned it seems it is not an applicable solution. Great video, Keep up the good work!

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      But if the DbContext is scoped - it should pulling the same scoped service to configure the Query Filter. Right?

    • @thanasakis61
      @thanasakis61 11 หลายเดือนก่อน

      true but my DbContext is scoped by default however the OnModelCreating get executed only the first time. A similar issue was discussed on StackOverflow about tenants on the same application.@@MilanJovanovicTech

  • @adnenbenawicha5082
    @adnenbenawicha5082 8 หลายเดือนก่อน

    Thank u for the video, can u make a video on migrations with multi tanécy please ?

  • @Wouldntyouliketoknow2
    @Wouldntyouliketoknow2 11 หลายเดือนก่อน +1

    It doesnt have to come from the JWT it can also be inferred from the url like a subdomain per tenant.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      That involves a whole lot more infrastructure, though

    • @Wouldntyouliketoknow2
      @Wouldntyouliketoknow2 11 หลายเดือนก่อน

      @@MilanJovanovicTech I disagree. Whilst it would typically require a wildcard SSL certificate (so that requests for multiple subdomains hit the ingress), I'm not sure that qualifies as whole lot more infrastructure as typically you'd have an ssl cert anyway. For local development you can add a few entries to your etc/hosts file e.g "foo.localhost" pointing to loopback ip. I would say it requires some very minor configuration to achieve. The main thing is whether its a requirement that tenants have their own subdomain. The benefits are it allows tenant identification prior to user authentication - so they can be served customised "public" pages and they can also have their own authentication / login page based on tenant settings - one tenant may use their own SAML idp versus another who uses native login. In other words the decision is more requirements based than infrastructural.

  • @dotnetMasterCSharp
    @dotnetMasterCSharp 26 วันที่ผ่านมา

    useful content

  • @dimitarelkov28
    @dimitarelkov28 11 หลายเดือนก่อน

    Come on… It is basic concept of multi tenancy. It’s a great presentation. For the goal of the POC it was kept simple as possible. Of course it can be extended based on everyone’s requirements. Important and focus is EF support here, because this can be achieved also without EF Core.

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Everyone wants to see a production-ready tutorial in 10 minutes these days 😁

    • @dimitarelkov28
      @dimitarelkov28 11 หลายเดือนก่อน

      @@MilanJovanovicTech people just don’t want to think

  • @marna_li
    @marna_li 11 หลายเดือนก่อน +2

    Thank you! Btw. The "X-" convention in "X-TenantId" is no longer considered necessary as per RFC 6648 🙂

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      I prefer having a convention for custom headers to make them easier to track

    • @drhdev
      @drhdev 11 หลายเดือนก่อน

      No longer necessary but good practice

  • @MarcusKaseder
    @MarcusKaseder 11 หลายเดือนก่อน +1

    The TenantProvider can be registered as Singleton. HttpContextAccessor is also a singleton. It uses AsyncLocal to ensure the scope.
    So, it is not important to register it as scoped ;-)

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +1

      Not important, but this is a simplified example. A more real-world scenario would be fetching the Tenant from the DB, which could leverage EF

  • @drhdev
    @drhdev 11 หลายเดือนก่อน

    I hope people understand that this is an example only and you should NEVER EVER do this in production

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน

      Which part exactly? Because we definitely used Tenant-based query filters in production on a 1M+ users SaaS.

    • @drhdev
      @drhdev 11 หลายเดือนก่อน +1

      The security part obviously. Query filters are fine. You’re treating a tenant like an api key when you should do a lookup on the user credentials.

    • @cloudwoofer
      @cloudwoofer 11 หลายเดือนก่อน

      @@drhdev yeah, I bet the video would get more and more complex the closer it is to reality so Milan chose to cut it short

  • @remyjoseacostamelo
    @remyjoseacostamelo 11 หลายเดือนก่อน

    🥷🏾🔥

  • @eugene5096
    @eugene5096 11 หลายเดือนก่อน +1

    Tenant could be passed via part of route

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 หลายเดือนก่อน +2

      Wouldn't that expose tenant info in the logs?