Building a multi-tenant solution can be challenging and full of risks. In this article we give some insights on how to decide when is the right time to begin using this architecture.
Multitenancy has been around us for quite some time, and it is frankly a very simple and powerful idea. However, with the growing demand for SaaS platforms along with the increasing need to reduce costs while innovating and fast delivering software, it has made its way back to modern software design, making it a critical piece of SaaS architectures, thereby turning great ideas into affordable ones.
What is multi tenant architecture?
It is a set of rules and constraints defined and enforced on our software design and its components with the goal of serving multiple tenants and sharing resources and instances.
In other words, it is a software construct that enables us to serve multiple customers using the same solution to share infrastructure and costs but not data or a customer’s proprietary objects.
How does this architecture differ from a regular user access filter?
Both may be implemented in a similar fashion, as both need to restrict user access, but they are meant to solve very different problems and use cases.
Let’s look at some of the differences here:
- User access filters based on roles or assignments are supposed to be flexible, configurable, and on many occasions, managed directly by customers.
- Tenants, on the other hand, are immutable, always enforced and frequently invisible to customers or even power admins. Once something is born on that tenant, it is meant to stay there until its end.
They are different, expected to be found in different hierarchies in our architecture (tenants are enforced before any user access stage), but they can also complement each other, as tenants can host multiple customers using their own user access configuration.
Is it as complex and tricky as it seems to be?
Building a multi tenant solution is not trivial; use cases for these kinds of applications must justify the risk and initial setup/design cost.
It also comes with its own learning curve. Keep in mind that when serving multiple tenants and getting the infrastructure loaded with several concurrent customers, applications, their composing frameworks, libraries, and infrastructure, it tends to behave completely differently than when they are working in a more controlled environment with just one customer using it. Designing it and choosing its technology stack needs to be thought out carefully and by experienced architects.
Nonfunctional requirements are as important as functional ones here — knowing how much load, concurrency, data volume, and quality of service that is expected is crucial. It is not rare to see multi tenant applications grow and eventually start getting short on capacity, thereby running into performance issues and data volume troubles.
Having some of the issues mentioned before could be a good problem if it were planned ahead, and the application was meant to grow and scale as it gets more usage and gets more traction from its tenant. However, it can also be a roadblock for the application if scaling requires some serious rework or a high-cost increase.
Ok then, how do we start?
We need to start from somewhere, right?
Let’s start from the most basic piece of this architecture — understanding what our tenant is going to be, as not knowing or scoping it properly may cause us to constantly rework and redesign it.
Always bear in mind that tenants are expected to be immutable walls in our solution that we would guard fearlessly. Having a tenant leak can jeopardize customers’ trust in our solution.
Having said all that, common definitions of tenants are Companies, Standalone Users, or Subscriptions.
Whatever we choose our tenant to be, it must be clearly understood by all product owners. Tenants are not supposed to share data freely between one another, and neither are they supposed to know about each other.
- Note that integrations between tenants may be a valid use case in some occasions, but these integrations should be seen like E2E integrations — foreign resources that require an explicit boundary to cross over and have both parties’ explicit agreement.
Once we have set in stone what our tenant is meant to be, our next step is to decide what resources are to be shared (web servers, databases, storages, licenses, etc.) and what resources are to be allocated to a specific tenant.
This decision needs to be an informed one, and it is a critical phase that drives the software design and implementation. This stage of the process is where cost, volumes, concurrency, growth, release cycles, technical resources, and budget should be considered.
This design process should take the following factors into account:
- Lower cost: As they are going to be serving multiple tenants, their cost is shared among multiple pockets.
- It is particularly useful and practical on expensive resources, thereby making our solution more competitive.
- These resources don’t need continuous provisioning since they are already serving tenants as they come into the solution on a pre-existing pool.
- It is not trivial to ensure availability, especially on critical resources. Some tradeoffs are required in order to get everyone served.
- Complex deployments and configuration management: Since this is a shared environment, everything impacts a broader public.
- Higher risk with security and data/tenants: Security is always a top concern with software, and it is not any less critical when sharing resources.
- It is simpler to ensure availability since there is only one tenant consuming it.
- There is a lower security risk due to the isolation of a dedicated resource.
- It is simpler to design and implement as it is a more familiar model for most software developers.
- Provisioning is not trivial: Dedicated resources for each tenant need to be spawned every time a new tenant gets onboarded.
- Maintenance effort grows as the number of tenants increases.
- Cost: It can make us less competitive if everything is dedicated to each tenant.
- It is not ideal for trials, freemiums, or testing subscriptions, as each one implies a direct cost.
Not everything needs to be black and white when deciding if a resource is to be shared or dedicated, but occasionally, it makes sense to have a hybrid solution. Each approach has its own benefits, so it may be a good idea to alternate between having a shared resource for some customers/subscriptions/features and dedicated resources for others willing to pay extra for some additional horsepower or exclusivity.
Some final thoughts
Building a multi-tenant solution is challenging, full of risks, and requires a few iterations to get it right, but it can also be a great opportunity booster.
When it is done right and our solution is capable of growing flawlessly and transparently to end-users, it opens the door to multiple sales strategies and reduces the stress on developing features and enhancements, as everything is done for a broader public and cost/risk is shared.
There are frameworks available for some major developing languages and platforms that could help us get started. These tools can introduce us to a multi-tenant business, but it may also be a limitation if it is not the right one for the job. There are no silver bullets after all.
Comments? Contact us for more information. We’ll quickly get back to you with the information you need.