About this talk
In this presentation, Alper, co-founder of Bsoft, discusses the ABP framework, an open-source application framework designed for .NET developers. He shares his experiences related to implementing multitenancy in software applications, highlighting the challenges and solutions developed over the years. Alper explains the importance of data isolation, tenant identification, and the architectural considerations involved in building multitenant applications. Additionally, he covers deployment models suitable for multitenant systems, such as on-premises and cloud-based infrastructures, while emphasizing cost efficiency and user experience. Real-world examples and code snippets illustrate how to manage tenant data while ensuring security and scalability.
Full transcript
[Music] welcome welcome to the last session of the morning um we are going to have Alper I'm not gonna say the surname sorry Alper it's going to be complicated EV kogu sorry for that um Alber is the co-founder of of bsoft uh and also he's um develops an open source framework for net.net developers he's one of the core maintainers so welcome Alper on stage I'm sorry again
for the serame I'm not so good in surnames impossible to say everyone's surname in different languages languages yeah how how how it's pronounced sorry perfect yes okay I'm gonna I'm gonna try next time I'm gonna try there Turkish Turkish C uh in my surname which is not available in other languages yeah yeah I can imagine on that okay perfect okay I'm gonna put the slides on stage
so you can start uh the presentation and for everyone feel free to ask your questions on the chat window Alper the floor is yours it's my turn hello everyone ladies and gentlemen thank you for joining me today my name is Alper and I'm one of the co-founders of woft and this company is uh empowering net developers by creating Frameworks and simplifying the complexities of software development and
we are trying to allow uh focus on your business so one of our Flagship project is the ABP framework this is a open- source powerful uh application framework and it implements many cross cutting concerns of a web application today I'm going to share my experiences and insights that I have gained while implementing major multitenancy requirements this is my first open source project and uh in this one
we have started in 2013 uh it's called ASB nut boiler plate we uh this repository has more than uh 11k stars on GitHub and we have released 200 versions it's one of our first multi-tenancy framework then we have Rewritten this Legacy framework uh to be F fully modular and multi-tenant and microservice compatible this one is called ABP iio uh ABP framework or so we have released uh
more than 200 versions so far and 12K stars on GitHub and 20 million downloads uh on nugget until now so why I'm showing you this because uh we have experienced uh a modular application development uh and uh we have a good experience on microservice architecture DDD and in the next slides I will show you how we solved some real world multi-tenancy issues and how we cover them
so asp.net core is a generic web application framework and many of us uh using this to build some HR CRM or um other Erp applications so generic web framework this asp.net core provides us essential features like routing dependency injection request response handling security issues and on top of the asp.net core there is ABP framework and it's an opiated architecture it focuses on to build a line of
business applications and it's trying to implement cross cutting concerns of a business application like exception handling caching localization validation transaction management social login something like this and also and in the final uh layer you can focus on your business and uh no need to deal with multi tency because uh I'm always saying uh these uh cross cutting concerns should be implemented in a core library or in
a framework level today's agenda is starting with introduction part and lat later I will talk you about uh advantages and disadvantages of later um I will show you some different scenarios of application and database deployments and sometimes um you need to change the active tenant but first we need to identify the active tenant so which uh which tenant is this tenant that this request coming from and
also data isolation is another issue of multitenancy uh how can we separate the different tenants data in uh virtually or physically later uh uh we we may need to conditionally turn off or turn on multitenancy for some cumulative reports or other things background jobs uh I'm going to show you how to do this in code and handling database migrations is also another issue if you have a
tiered application and different environments geolocations and finally if we have time uh I will tell you a little bit how we implemented our feature system so multitenancy uh is an architectural approach it's nothing to do with asp.net core in all language or platforms you can create your own multi-tenant applications it's for building SS applications software as a service platforms and in this approach hardware and software resources
are shared uh between your tenants and uh tenants data and configurations are logically or separated and in this terminology there is tenant and host tenants are our customers clients who are using the system and host uh you the solution owner the service provider and uh bear in mind that multi tenen system should be designed to work seamlessly and make your application code multitenancy unaware as much as
possible you shouldn't pass tenant ID to all your url parameters controllers application Services repositories domain Services um it will be also open to human mistakes if you pass this tenant ID to all these layers also uh do all tency related stuff in a low level uh layer and and keep your business Cod clean as much as possible and uh when your customer uh wants you to deploy
this application on their environment you you should be able to deploy it on premise as well so don't stick to any clo service or any uh in maybe your uh custom environment it should be also deplo Deployable to customers there are different service models SS service models uh the first one is on premises which is not uh SS friendly uh you need to deal with all kinds
of different stuffs like networking electricity Windows updates database management everything is under your control it's called on premise you you install it to your customers's environment or to your environment and you will deal with everything the second one uh there are some different options uh virtualization servers storage networking these are maintained by the third party who are uh which you already getting service and for this model
Google compute engine is an example aor virtual machines is an example so uh you are using the infrastructure sometimes you may need it if if you are running custom executables or need to do some custom things in operating system you may need this environment also there is another model pass platform as a service in this model you only deal with your application and database other things are
managed by the third party uh for example azur up service Heroku Google app engine these are examples and lastly the real uh service model you will not deal with all platform or infrastructure level things all these are maintained by the service provider like Discord zoom Gmail Netflix these are uh S Services so there are advantages there are many advantages of multi tenen but I will count most
uh five important of them first of all it's it's cost efficient what what I mean you share the hardware and software among your customers and you reduce uh costs and serve the maximum number of customers so you maximum uh maximize the utilization and secondly you will have a consistent user experience because all your all your customers are using the latest version and we as developers can focus
on maintaining a single code base ensuring that all tenants receive updates and improvements at the same time and third one ISE of Maintenance so uh maintaining a single code base and infrastructure for for all tenants simplifies our software updates P patches uh bug fixes and also so it reduces the complexity of managing multiple instances making it easier for our life to maintain the system and scalability is
also another one uh when there are demand spikes you can easily increase system resources like when there is a Black Friday season you can uh add more instance of your application uh behind your load balancers easily but imagine that if it was an on premise system it will be very hard to set up new environment to scale up your system and also deployment uh is very easy
for new users because whenever a tenant uh on boards it is just a new line of uh database table record and that's it he will be using the system in the same no need to set up uh anything for your client I'm going to show you uh real life code uh that we implemented in the framework these are description Parts met metad datas and boring part and
there are some challenges of creating uh a multi-tenancy application actually first of all uh we are isolating data Maybe in the same database or we um physically separate their databases and you need to ensure proper data isolation between your tenants to prevent unauthorized access to sensitive information if you cannot do this or imagine that a junior developer joins the team and he forgets some tenant ID in
a query what happens everyone all your tenants will see everyone's data so you need to do this in a framework level and uh you need to guarantee the tenant ID will be added to all queries as a filter and your clients sometimes request you to customize the application according to their requirements because uh they will have their own uh branding colors UI logo uh they will want
to change the color schema and maybe they will have different uh retention policies so it will be hard to uh develop an application uh for different tenants to be fully customizable without compromising the core architecture so we cannot write if customer is Nik change this or so you need to allow customers to change customization options from a UI also there is a performance balance problem some customers
may use the system extensively so we call these guys nois Neighbors in multitenant environment and these can consume too resources and we should ensure that the resource usage of one tenant doesn't affect negatively uh the performance of another so this should be done by monitoring the system and uh you may need some extra devop devops tools for this one security is a crucial option uh in this
one when a hacker gets into your server he can steal all your tenants data also if you have a security hall a tenant gain access to other tenants data so you need to ensure that uh you cover all oasp uh security uh problems issues it's another challenge and also backup recovery uh is another thing this involves database and storage backup per tenant it will be very easy
to backup restore when you have a separate DB for each tenant but if you have a shared DB then you need to get back up of a specific tenant you need to gather information from different database tables and it should be restorable also your customers will may have different retention policies so you need to implement different strategies for each tenant for maybe government agencies and Banks uh
this is different database and deployment architecture scenarios in the first one uh it's on premise style deployment not SS friendly you deploy your application or instance and database for each your tenant uh it's not very SS friendly in the second one you share your application instance with uh among all your customers but each of your customers uh will have separate database this is good but uh not
good for resource utilization and it's also hard when you have update your instance maybe your database schema is also uh needs to be updated you cannot update everyone's database at the same time but when you update your application server it will check uh other databases and if the one of the tenant database is not upgraded they will get exceptions also uh you need to figure out how
to deploy this databases in the second model in the third one this is s friendly maximum utilization customer uh customers will share the same application and they will share the same database but it will not be very feasible because they will ask to separate their DB like Banks Banks will not accept to be in the same shared database or government agencies they sometimes uh tell for the
gdpr rules they need to locate their database in their country so the third fourth one hybrid model covers all these requirements if a customer pays more you can separate their database and if not uh they can be in the same database so uh we um web developers know that HTTP is a stateless protocol what is stateless protocol means user data is not persisted from one page to
the next and our web application multitenant web application should also be stateless and the Tenant ID shouldn't be stored on the server uh because when you store it on the server you cannot scale up there will be different servers One customer logins in a one web server you store their tenant ID the other servers doesn't know don't know their uh tenant ID and the next request may
go to the uh other server which doesn't know the tenant ID so this is not good friend also stateless approach is multi thread friendly then where should we save the state we can save in HTTP requests cookie or header or query string or payload of the request also you can save it the tenant ID in authentication tickets as gvt or in DB or in distributed cache like
radis M cach these are all good options to save tenant ID okay up to now I I gave you general information about multitenancy now let's see some code and real world solution I gathered some uh code from uh ABP framework and these code are simplified versions of uh the real code because I want to focus and uh make you understand easily what's going on in the code
section that I will highlight so when a user makes a request to the application you need to understand which tenants user is this user there are six ways of finding the current tenant active current tenant in our implementation and these six are all fallback of the previous one so we will First Look to current user let's see how to do this so claims when a user logs
into the system we can save his tenant ID to the claims and when the user comes back again we can identify the user from the claims and it's very easy in asp.net core uh in the framework we are using a current uh user uh o object here I current user and uh the current user. tenant ID is just HTTP context user identity claims uh collection and we
are filtering tenant here if you cannot find find in the claims then you can search in query string yes also query string is another way of uh storing tenant ID here you see tenant ID is three or you can write it write the tency code like tenant is uh Adidas and you can get it from HTTP context request query uh object and next if you didn't find
uh uh URL parameters you can use routing here akme is a part of our URL and we can easily get this route value from HTTP context get route value uh method and if you find this retrieve this tenant ID if you still cannot find let's go uh fall back to the next one we can get the tenant ID from request header here our application sends the tenant
ID itself it's a good here uh and we can easily get the tenant ID from HTTP context request headers collection and it's good for single page applications also third party clients like mobile apps you didn't find in uh header then you can jump to cookie cookie is also good place to store your tenant IDs here I'm sending tenant ID in my request cookies and uh in my
uh server code I can read it uh from HTTP context request cookies collection and lastly if you didn't find all these uh from all these places you can use subdomains it's also good one especially if you are making an e-commerce online shopping website you can use the subdomain here like Addidas do uh ESP sports.com n.s sports.com you can read this value by getting request host value and
uh you may need to write just a simple regular expiration parse method I didn't write the inside content of the parse but you can easily get this part and you can use this uh as your tenant uh tenant name and you can uh set the active tenant from this uh part okay we see how to identify the active tenant let's understand how can we isolate the data
actually uh there are two ways logically or physically let's see uh the traditional way when you have a repository this entity is books entity this is how you normally do this you filter the tenant ID uh you get the active tenant uh from my previous slides the current tenant and current tenant ID uh equals to my uh tenant ID in my uh repository table but it's open
to human mistakes because you can forget this I'm going to show you how to make it uh automatically parsed in a framework level so we are creating a im multitenant interface and in this interface we have a guid nullable GID tenant ID so we are uh standard we are making standard the tenant ID field so uh in the following slides I will show you how can how
I will uh parts or how I will set this ID programmatically in uh application so to filter a tenant ID in your application globally there is very good uh feature of Microsoft Entity framework core it's called Global query filters and uh this is good for uh filtering uh it's a filter condition automatically applied to all the queries for a given entity so it's good for soft soft
delete multi-tenancy or if it's a bookstore application published is published field you can use this it's a linku expression that applies to entities on model creating phase so you do like this in your DB context on model creating phase you write H query filter and it will automatically add all your queries in your repository but let's see how can we how can we make uh it automatically
uh filtered in our application so in the framework we are checking uh in this is again in DB context and we create our own DB context ex uh inheriting DB the original EF course so we check if our entity is an IM multitenant entity if yes we are creating a new linku expression we get the current tenant ID from active scope and make the make create a
new expression here and and we are using has query filter of EF core and adding it globally so you will not miss uh the this one in all your queries it will be automatically at in the framework level like this so you need to just add IM multitenant to your entity and that's it it will be globally filtered by tenant ID this is good uh easy to
implement supports navigation properties but works only with ef core and it also have some drawbacks because uh when you want to disable a query you cannot uh there is an option to uh disable filters but it filters all the uh filters like multi tereny soft delete every Everything also uh if you are planning inherit an object from animal like big animal small animal you can Define this
only to animal so uh Global query filters work on the root entity also if you want to use uh stor procedures or row SQL SQL uh queries it's not supporting uh these are ignored in uh EF course Global query filters but there is a good NES for this one you can use Microsoft uh if you are using SQL server or a SQL data base you can use
row level security in this option all the the tenant ID is filtered automatically uh in the database level so even if you write open the SQL management studio and write your own tsql it will be filtered for the uh tenant because it depends on the connection string but again uh you are sticked with the seal uh server if you want to change it later you need to
build all these multi teny features again so for me uh pragmatic solution is uh EF course uh filters also um if you are not using EF core uh let's say we are creating a application on top of mongod DB document DB it doesn't have this option like EF core no Global query filters so in this kind of uh scenario you can create your own Global query filter
how can you do this uh so you will again use IM multitenant interface to check if your uh entity is multitenant or not you will create your expression uh tency uh filtering expression and then you need to add it to your custom Global query filters and uh you need to uh use your uh mongodb repositories uh to filter this so uh it's a uh workaround of how
to make custom Global filters for mongod DB uh we see these options uh how to identify the active tenant and isolate the data let's see how to set the tenant ID actually when you create a new entity you can set it manually but U again it will be uh open to human mistakes you can easily forget to set tenant ID so I am suggesting you to create
your base is uh entity class which can be abstract and uh in the protected uh entity Constructor you can check if it is a im multitenant entity if yes by the help of reflection and you know that uh you have tenant ID it's standard we standard make it standard with this interface you can set the tenant ID you can get it from the current scope like and
set whenever a new entity is created so again in the framework level or your Library uh this will be automatically done the creating a new tenant so you will not forget any tenant uh ID setting let's see how to uh select the because when you have uh shared database okay it's not problem but when your customers uh have separate data databases what will you do so in
my uh framework we are doing uh this in a database table so we have a app settings Json file in this app settings Json file we have Master DB connection this is stored in the app settings Json and uh when the application gets a new request from a tenant we first check this table if uh this customer has a custom connection string here because here tenant ID
and connection string value stored here then we are using uh this connection string to start up the DB context of this customer also you can do this for uh any custom micros service so when a new microservice boots up you can check uh its database uh connection string uh if it's here then you can use if not you can use the default connection string which is shared
I'm going to show you how to do this in code so here uh we have default connection string resolve resolver this is uh a framework uh Base Class and we are creating our own uh multitenant connection string resol resolver so we know the current tenant ID from the previous slides and we check the database you can uh make caching here so not every time you get you
go to the database uh I deleted these parts because to focus you here and we see this tenant has a dedicated DB and we are resolving their uh connection string here and we are using Microsoft's uh DB context creation options approach DB context cre creation options uh allow you to set connection string each time when a DB context is being created so uh every customer every tenant
can have dedicated DB or they can DB uh if we implement this so until now uh we identify tenant we isolate data we set the tenant ID for new entities automatically we select the uh proper connection string for the customer now it's time to change the active tenant why we need to change this tenant uh in each HTTP request you can only query for the active tenant
it may be necessary to change the active tenant for example when you have a background job that generates reports for each tenant you need to iterate through your tenants and you need to change this tenant every time you switch to other tenant to create reports or cumulative data so how we do this this is how uh how the developer use this current tenant change and they provide
tenant ID and inside this using block all the queries will be filtered by this n tenant ID if even this tenant the active tenant is a different one so it's an disposable I disposable method you see the implementation here we get uh we store the current tenant in a temporary uh variable and here we are creating a basic tenant with only name and ID and whenever the
code run finishes we revert back to the original tenant uh we stored here with the dispose action so that uh we don't forget to change back to the original uh tenant every time we change so you see here I'm also using Uh current tenant change this is the main uh multi-tenancy filtering middleware this is the startup uh file of my application a and uh I'm looking to
one field one flag multitenancy enabled if it's uh enabled in my application wi then I'm using this middleware uh and changing tenant uh for disabling multitenancy uh we have another option we are using a Singleton dependency here we have concurrent dictionary that uh all the filters are in this dictionary and when we disable this uh we first check here is if my uh multi-tenancy filter is enabled
because I'm getting I multitenant filtering from this uh object and if it's enabled I'm using EF course Global query filters if not I'm not using it here okay I'm going a little bit faster to explain I have have no time I think uh in I will explain you different migrations approach one and approach two uh I'm not suggesting these options for uh highs scale options you can
create a custom tool update all the databases but it's time consuming uh you cannot update everyone's database also in the second approach uh when a tenant makes a DB interaction you can trigger their data database migration but it's also not good for the first user he will take he will get uh timeout exceptions and concurrency problems and this is uh the suggested way sometimes uh okay in
the old version uh left side in the graphic you see uh we have our Legas application and in the new platform we have uh the updated version our a server is updated and database schema is updated so when a user comes to our system we first check if his dat his system is updated if not we root it to the uh old version if yes you root
your customer to the new application server by doing so you will uh wait your customer customers uh in a minimum time also you can schedule upgradings for your tenants you can run AB tests and see buxs before uh new customers or any other big uh customers so this is good and uh this is how Google updates their Gmail in the old times so in the old times
I see Gmail updated the UI I was uh experiencing the old version but my friends already using the new version because their application and DB is updated and uh Google Roots these people to the new environment and I got an email that's saying uh my UI will be updated in the next following weeks and I will experience the new platform so this is the uh ideal way
for big systems um if you have time uh I will I can explain you future system so future system is when you you create a uh subscription based platform you will have different plans and you will have different features here you see Netflix HD available option it's not available in basic and standard premium they offer how we do this Microsoft solution feature system uh nugget package when
you search internet you will uh see first this one but it's not good it's not for uh feature management system this is for azour AB testing it doesn't support multitenancy as well and it only supports Boolean values so you can create your own feature system here uh future definition provider this is uh my custom class here and Futures are stored in my readon list and whenever uh
a method runs I can add attribute here requires feature and I can intercept the uh method and check is HD available option is uh available for tenant also you can make uh inline checks conditional checks like this in your method so it works in any class that is injected from dependency injection so just uh create an i feature Checker uh interface and inject the uh methods like
this or allow developers to uh query this feature conditionally and you can easily uh render these features that stored in your uh readon list here on a UI so you can create your own uh subscription plans and different editions so uh this is all from my side uh thank you for listening to me if you are interested in these options and uh how we buil this I
showed you a little Limited uh features uh to make this presentation in time you can go to abio it's open source free uh you can check if you want to download this presentation uh you can download it my from my G presentations repository and uh I think we finished our time five minutes yes well we have a couple of minutes left uh just in case that we
have some questions from the people but uh nothing appear at the moment so I will give a couple of um a minute something like that uh thanks Alper for your presentation actually do you have any questions I think yes I removed myself accident yeah yeah I have I have uh many questions but I I think that we don't have uh we don't have too much time um
good to see that net it's well Microsoft in the end it's also investing in open source Technologies and and and Frameworks so that's something cool to see uh at least from my side knowing uh uh Microsoft for a for a long time so yeah it's it's it's cool to to see that um aside that you called for Action what where else we can collaborate with this uh
project aler in in in in the GitHub or going to yes Twitter as you see uh on the screen https ab. on the right side here this is the uh website and when you go there you can find the repository uh link you can check out it's also good for DDD also uh microservice uh uh features you can check and understand how we implement this because there
are many contributors uh in this Frame framework who make this framework uh uh consistent and uh rack solid uh it's also good uh source for educational uh checking cool cool okay cool thanks thanks a lot Alper um I don't see questions on the chat so we can finish the session for today thanks a lot for being with us uh having this talk with showing what you are
doing and your project uh for the people still watching um we will have a lunch break uh after this talk we will return at let me check because before I say the the time a little bit uh a little bit wrong mainly because I have two different um windows and tabs that says obviously one the local time and then my local time uh so at40 p.m. uh
European Central Time uh it's going we are going to return with what the what the f commit messages uh by Andre snev and for the people that are watching from the gm3 plus three you are watching from Lithuania you're watching from any other Baltic area it's um 2:40 p.m. uh so we will see in about one hour from now uh thanks a lot and see you soon
thanks Halper have a bye everyone have a great conference
More from this event
See all 73 talks →
Tomas Lekavicius: Building Tech Product Offer
42:08
Alisa Dammer: Science and Tech Backed Approach to Increase Productivity
44:53
Roy Wasse: The Definitive Answer to Measuring Developer Productivity
44:47
Pierluigi Meloni: You’re a Great Coder? That Alone Won’t Get You Far
44:47