Multi-tenant architecture, commonly referred to as multitenancy, is a software architecture in which multiple single instances of software run on a single physical server. The server then serves multiple tenants. Additionally, multitenant architecture is used to enable multiple users to use a single application, for instance a database.
Multi-tenant architecture is often used in cloud computing, to offer shared tenancy on public cloud providers like Amazon Web Services, Microsoft Azure and Google Cloud. Additionally, multitenancy is a key part of another cloud model, software as a service, and so is deployed by many SaaS companies as well as virtually every cloud company.
Potential benefits of multi-tenant
Affordable Cost: Multiple customers means that the cost for the environment is shared, and those savings (from the SaaS vendor) are typically transferred to the cost of the software.
Integrations: Cloud environments allow for easier integration with other applications through the use of APIs.
“Hands-free” Maintenance: The server technically belongs to the SaaS vendor, meaning that a certain level of database maintenance is handled by the vendor, instead of you maintaining the environment yourself.
Potential drawbacks of multi-tenant
Limited Management/Customization: While you do have added integration benefits, custom changes to the database aren’t typically an option.
Security: Other tenants won’t see your data. However, multiple users (not associated with your organization) are allowed on the same database. This broader access reduces control of security.
Updates/Changes: If you’re reliant on integrations with other SaaS products and one updates their system, it may cause issues with those connecting apps.
Azure App Service is a powerful web application hosting platform. Azure Functions, built on top of the App Service infrastructure, enables you to easily build serverless and event-driven compute workloads. Both services are frequently used in multitenant solutions.
Features of Azure App Service and Azure Functions that support multitenancy
Azure App Service and Azure Functions include many features that support multitenancy.
Custom domain names
Azure App Service enables you to use wildcard DNS and to add your own wildcard TLS certificates. When you use tenant-specific subdomains, wildcard DNS and TLS certificates enable you to easily scale your solution to a large number of tenants, without requiring a manual reconfiguration for each new tenant.
When you use tenant-specific custom domain names, you might have a large number of custom domain names that need to be added to your app. It can become cumbersome to manage a lot of custom domain names, especially when they require individual TLS certificates. App Service provides managed TLS certificates, which reduces the work required when you work with custom domains. However, there are limits to consider, such as how many custom domains can be applied to a single app.
Integration with Azure Front Door
App Service and Azure Functions integrate with Azure Front Door, to act as the internet-facing component of your solution.
Azure Front Door enables you to add a web application firewall (WAF) and edge caching, and it provides other performance optimizations. You can easily reconfigure your traffic flows to direct traffic to different backends, based on changing business or technical requirements. When you use Azure Front Door with a multitenant app, you can use it to manage your custom domain names and to terminate your TLS connections. Your App Service application is then configured with a single hostname, and all traffic flows through to that application, which helps you avoid managing custom domain names in multiple places.
Authentication and authorization
Azure App Service can validate authentication tokens on behalf of your app. If a request doesn't contain a token, the token is invalid, or the request isn't authorized. App Service can be configured to block the request or to redirect to your identity provider so that the user can sign in.
If your tenants use Azure Active Directory (Azure AD) as their identity system, you can configure Azure App Service to use the /common endpoint to validate user tokens. This ensures that, regardless of the user's Azure AD tenant, their tokens are validated and accepted.
You can also integrate Azure App Service with Azure AD B2C for authentication of consumers.
You can restrict the traffic to your app by using access restrictions. These can be used to specify the IP address ranges or the virtual networks that are allowed to connect to the app.
When you work with a multitenant solution, be aware of the maximum number of access restriction rules. For example, if you need to create an access restriction rule for every tenant, you might exceed the maximum number of rules that are allowed. If you need a larger number of rules, consider deploying a reverse proxy like Azure Front Door.
When working with a multitenant system using Azure App Service or Azure Functions, you need to make a decision about the level of isolation that you want to use.
When you work with Azure App Service and Azure Functions, you should be aware of the following key concepts:
In Azure App Service, a plan represents your hosting infrastructure. An app represents a single application running on that infrastructure. You can deploy multiple apps to a single plan.
In Azure Functions, your hosting and application are also separated, but you have additional hosting options available for elastic hosting, where Azure Functions manages scaling for you. For simplicity, we refer to the hosting infrastructure as a plan throughout this article, because the principles described here apply to both App Service and Azure Functions, regardless of the hosting model you use.
Plans per tenant
The strongest level of isolation is to deploy a dedicated plan for a tenant. This dedicated plan ensures that the tenant has full use of all of the server resources that are allocated to that plan.
This approach enables you to scale your solution to provide performance isolation for each tenant, and to avoid the Noisy Neighbor problem. However, it also has a higher cost because the resources aren't shared with multiple tenants. Also, you need to consider the maximum number of plans that can be deployed into a single Azure resource group.
Apps per tenant with shared plans
You can also choose to share your plan between multiple tenants, but deploy separate apps for each tenant. This provides you with logical isolation between each tenant, and this approach gives you the following advantages:
Cost efficiency: By sharing your hosting infrastructure, you can generally reduce your overall costs per tenant.
Separation of configuration: Each tenant's app can have its own domain name, TLS certificate, access restrictions, and token authorization policies applied.
Separation of upgrades: Each tenant's application binaries can be upgraded independently of other apps on the same plan. However, because the plan's compute resources are shared, the apps might be subject to the Noisy Neighbor problem. Additionally, there are limits to how many apps can be deployed to a single plan.
You can also consider deploying a shared application on a single plan. This tends to be the most cost-efficient option, and it requires the least operational overhead because there are fewer resources to manage. You can scale the overall plan based on load or demand, and all tenants sharing the plan will benefit from the increased capacity.
It's important to be aware of the App Service quotas and limits, such as the maximum number of custom domains that can be added to a single app, and the maximum number of instances of a plan that can be provisioned.
You can host APIs on both Azure App Service and Azure Functions. Your choice of platform will depend on the specific feature set and scaling options you need.
Whichever platform you use to host your API, consider using Azure API Management in front of your API application. API Management provides many features that can be helpful for multitenant solutions, including the following:
A centralized point for all authentication. This might include determining the tenant identifier from a token claim or other request metadata.
Networking and multitenancy
Many multitenant applications need to connect to tenants' on-premises networks to send data.
If you need to send outbound traffic from a known static IP address or from a set of known static IP addresses, consider using a NAT Gateway.
If you don't need a static outbound IP address, but instead you need to occasionally check the IP address that your application uses for outbound traffic, you can query the current IP addresses of the App Service deployment.
Because App Service is itself a multitenant service, you need to take care about how you use shared resources. Networking is an area that you need to pay particular attention to, because there are limits that affect how your application can work with both inbound and outbound network connections, including source network address translation (SNAT) and TCP port limits.
If your application connects to a large number of databases or external services, then your app might be at risk of SNAT port exhaustion. In general, SNAT port exhaustion indicates that your code isn't correctly reusing TCP connections, and even in a multitenant solution, you should ensure you follow the recommended practices for reusing connections.
However, in some multitenant solutions, the number of outbound connections to distinct IP addresses can result in SNAT port exhaustion, even when you follow good coding practices. In these scenarios, consider deploying NAT Gateway to increase the number of SNAT ports that are available for your application to use, or use service endpoints when you connect to Azure services, to bypass load balancer limits. Even with these controls in place, you might approach limits with a large number of tenants, so you should plan to scale to additional App Service plans or deployment stamps.