December 2, 2015

The Benefits of Multi-Tenant Architecture

Product development is an ever-expanding endeavor. Starting with a simple idea targeting a niche user base, we gradually keep adding features to improve usability and adapting to continuously changing market requirements.

If we are offering our product to a third-party that will then be offered to their consumers, we need to ensure that the product caters to two levels of users. The end user will want certain business processing, which will depend on the industry domain. The direct clientele will require certain rules on how the business processing is conducted, as in security, validation, and its own business drivers, along with their own corporate branding.

Architecting the product for one such client is an easy job. There’s just one party to listen and cater to, even if they have a lot of requirements. But if we limit ourselves to just one client, we will be losing on business. This is because we will be ignoring several prospective clients in the same business domain who differ a little in their ways of providing value.

3Pillar got to work on such an opportunity to develop a solution for a client who would white-box it and sub-lease it to its own clientele, which are themselves service providers to end customers, the public.


This required us to cater to the core need of having a pre-paid card and its associated operations, along with the specialized needs of each co-branded partners (stores, restaurants, parking lots, etc.). 3Pillar understood this vision and identified the need for a Multi-Tenant-Architecture. The design goal is that all of the layers – core, business, data storage and user interface–have an adaptability layer built on top of a base layer.

Multi-Tenant Architecture

An architecture can be MTA-enabled at any or all layers depending on the type of situation and level of customization required. The architect can:

  • Choose in which layers to implement multi-tenant awareness, and
  • Choose which strategy to apply at any desired layer based on the client’s needs.


Tenant Identification

This is the core process because it identifies what type of customization to apply. This is done by identifying the end user via some kind of log-in process, where the system will identify from where the request is coming. In usual cases, this will be the website of the business where the end customer is doing the transaction. The output of this process is made available system-wide for usage in any layer, which means it is multi-tenant aware.

Custom Branding at Presentation

Since every business has its own branding, the presentation branding is selected based on the tenant identifier and loaded from the content library as a single theme comprised of stylesheets, images, and layouts. The application will continue to look the same from a functional perspective, but the element design will adapt to the brand utilized by the end customer for their needs. All of the presentation components support tenant-specific settings as name-value pair configurations, with settings to indicate which form fields or action buttons should be rendered to end-users.

The presentation layer may also provide custom data entry/usage fields designed through tenant-specific templates, enabling their specific business rules.

Business Rules Adaption

All businesses have some core rules corresponding to their domain. They place additional validations and customizations on top of the core functionality as their differentiating factor. While every customer will require the core business task, they will always welcome the customizations and special features, which provide more usability.

These customizations are developed specifically for each tenant, and can be setup as a plugin, which can be made by tenant’s own IT teams. These can be turned on and off based on various laws and marketing strategies of the business as well.

For example, a coffee shop may allow an adult to reload a pre-paid card with any limit, but restricts children to a certain limit. This can be implemented as a runtime check, designed as per Decorator principle, upon the core business function of reloading; which will be common across the tenants. The runtime will identify the business rule using the tenant identifier and then drive the flow using the customer’s profile to restrict the amount. Since the decorators can be built over each other, the system can support any number of customizations, all of which can run in parallel or be driven in a sequential manner.

public interface ICardMaintanence
    void Transact(string cardNo, double amount);
public class Common.CardMaintanence : Contracts.ICardMaintanence
    public void Transact(string cardNo, double amount)
        lock (cardNo)
            var card = this.GetCard(cardNo);
            if (card.Amount >= amount)
                card.Amount -= amount;
            else throw new Exceptions.InsufficientBalanceException(cardNo, card.Amount, amount);
public class Client_ABC.CardMaintanence : Contracts.ICardMaintanence
    public void Transact(string cardNo, double amount)
        lock (cardNo)
            var card = this.cardMaint.GetCard(cardNo);

            // Impose business rule
            if ((card.Owner as Owner).Age < 18)
                if (amount > 25)
                    throw new Core.Exceptions.AmountLimitExceededException(cardNo, amount);
                // Delegate call to the default implementation
                this.cardMaint.Transact(cardNo, amount);

The client’s implementation will be chosen through a dependency injection mechanism, whereas the set of business rules will be chosen through a business rule engine that selects which rules are in force for the given tenant.

Data Layer Based on Scalability

The database implementation can be designed in three different ways, depending on tenant’s client base and their independence needs. The cost, independence, sophistication of customization, and scalability of the client base are directly proportional to each other and grow as we move towards a design as a result of having isolated database for each tenant.


  1. Separate Database: The tenant will get a separate database, created as clones of the core structure, but customized independently as per their own requirements. Entire maintenance operations are done independent of other tenants, which allows for maximum isolation, security, efficiency, and scalability, but at the cost of individual maintenance.
  2. Shared Schema: This has a single database instance and all tenants store their data under a tenant-identifier. The procedures are common to every tenant and use the tenant-identifier to locate the correct schema. This is specially suitable for tenants that have a very small user base, because the low cost will give them an easier entry point. No customization is possible in this because all of the tenants share the same database system.
  3. Separate Schema: As an in-between of the previous two options, this option has each tenant owning their own schema, which contains their own data-objects. This  gives them a layer of logical separation.

In the data layer, we can offer all three designs and the tenants can choose the level of freedom they want. These kinds of offering also allow a startup tenant to begin with shared schema and then have a scalable roadmap to move to separate database instances.

Multi-tenancy presents us a great way to have our architecture supporting different clients while still being modular and scalable. It improves our return on investment on system development by allowing multiple clients and, as a result, more revenue.