Skip to content

What is multi-tenancy

Defining multi-tenancy

Multi-tenancy refers to serving the same application for multiple tenants from a single codebase.

The opposite of multi-tenancy is multi-instance, where you’d host the application separately for each tenant. Multi-instance comes with a significant DevOps complexity, which is what multi-tenancy tries to prevent.

The basic idea behind multi-tenant applications is that:

  1. You use the exact same code for all tenants
  2. The data is what’s different for each tenant

This may sound a bit like simply having an application that multiple users can use, where each user can only see their own data. And that is technically multi-tenancy, by the most broad definition of the term.

However, in the context of this package we use a bit more specific definition to make the term more meaningful:

  1. Applications that are served from a single codebase for multiple tenants
  2. The tenants all have their own data, and may also have configuration that affects the behavior of the app (branding, features only available on a certain plan, …)
  3. The tenants have their own users
  4. Tenants are specified in the HTTP requests, usually by domain, path prefix, or some header

The third qualification is important here. If you simply want to let multiple “people” use your app and have their own data, you could just use Laravel’s native authentication, and use the current user to determine what data to show.

But in the more meaningful sense of the term, multi-tenant applications are applications like Shopify: each tenant essentially gets their own e-commerce application that has its own users, administrators, orders, branding, etc — but it’s still served from the same Shopify codebase as all other Shopify apps.

A multi-tenant app may or may not be a SaaS. There are completely valid non-SaaS use cases for multi-tenancy, such as serving the same app for multiple departments with full data isolation.

Different models of multi-tenancy

Multi-tenancy is commonly separated into:

  1. Single-database tenancy: having all tenant data in the same database. Essentially using tenant_id columns to separate data
  2. Multi-database tenancy: having a separate database for each tenant

Both come with their advantages and disadvantages. Single-database is simpler on the DevOps side — you don’t need to migrate and backup more than a single database — while single-database is simpler on the code side — you don’t need to write any manual query scoping logic.

In the context of our package, we further separate multi-tenancy into automatic and manual:

  1. Automatic mode: automatically making your application tenant-aware when a tenant is identified, typically using Tenancy Bootstrappers to reconfigure services registered in Laravel’s service container
  2. Manual mode: handling all tenant scoping manually and only using the package’s logic to identify the tenant from the HTTP request

Don’t worry about this distinction too much. In practice, nearly everyone uses automatic mode. The point is just that the package can be used both for making your application tenant-aware automatically in the background, as well as for simple tenant identification using middleware without any tenancy logic. It’s all configurable using our event system.