Contents

Multi-tenancy is an architecture in which one application serves many customers while their data stays isolated. At the start, most SaaS products are well served by a shared database with a tenant ID in every table: it is cheaper to maintain, and large customers with special requirements can later move to separate databases.

Here are the three multi-tenancy models, their pros and cons, ways to prevent data leaks and how to choose a model for your product.

What multi-tenancy models are there?

There are three main models: all customers in shared tables, a schema per customer in a shared database, or a database per customer. The stronger the isolation, the higher the infrastructure cost and the harder the updates.

Model Isolation Cost Schema updates When to choose
Shared tables with tenant_id Logical Low One migration Most SaaS at the start
Schema per tenant Medium Medium A migration per schema Tens to hundreds of B2B customers
Database per tenant Full High A migration per database Regulatory requirements, large contracts

How do you make a shared database safe?

In a shared database every table with customer data has a tenant ID, and the filter on it is applied automatically rather than by hand in every query. A forgotten filter is the most common source of data leaks between customers.

// Global scope: every query on the model is filtered by the current tenant
class TenantScope implements Scope
{
    public function apply(Builder $builder, Model $model): void
    {
        $builder->where($model->getTable() . '.tenant_id', Tenant::current()->id);
    }
}

Extra layers of protection:

  • PostgreSQL row-level security policies as a second line of defence;
  • the tenant ID in composite indexes and unique constraints;
  • automated tests checking that tenant A cannot see tenant B's data;
  • separate prefixes for each tenant's cache, files and queues.

For common web application vulnerabilities, see OWASP Top 10 explained.

A lobby with elevators and a reception desk Photo: Unsplash

When does a customer need a separate database?

A separate database is needed when a customer requires physical data isolation by contract or law, when data must be stored in a specific country, or when one customer generates load comparable to all the others combined. It is usually an enterprise plan with its own price.

The cost of isolation:

  1. Migrations must run across every database, making sure none falls behind.
  2. Cross-customer reports are assembled from many sources.
  3. Backups, monitoring and connections multiply with each customer.
  4. Each new customer needs a database — automate this at sign-up.

What should you choose at the start?

At the start, choose a shared database with a tenant ID in every table and automatic filtering. It gives a fast launch and cheap maintenance, and with the right groundwork lets you move individual customers into isolated databases later.

What to build in from day one:

  • a tenant ID in every table with customer data, even if it seems unnecessary now;
  • resolving the current tenant in one place — by subdomain, domain or token;
  • plan-based limits so one customer cannot take every resource;
  • per-tenant data export — needed both for migration and for legal requests.

We wrote about linking architecture to pricing in SaaS pricing model and SaaS unit economics.

How do you avoid noisy neighbour problems?

A noisy neighbour is a customer whose load slows everyone else down. The defence is limits and resource separation: heavy operations go through queues with per-tenant quotas, and the API limits request rates.

  • API rate limits per tenant and plan;
  • separate queues or priorities for imports, exports and reports;
  • load monitoring broken down by tenant to see who generates it;
  • moving large customers to dedicated resources without code changes.

In short

  • Multi-tenancy means one application for many customers with isolated data.
  • Models: shared tables, schema per tenant, database per tenant — isolation grows with cost.
  • A shared database with tenant_id and automatic filtering fits the start.
  • Global filters, row-level security and automated tests prevent leaks.
  • Large customers and regulatory needs are handled with dedicated databases later.

FAQ

  • Can you move from a shared database to separate ones later?

    Yes, if every record has a tenant ID from the start. Then one customer's data can be exported into a separate database without rewriting the application.

  • How do you give customers their own domains?

    The application identifies the tenant by the request's domain or subdomain, and certificates are issued automatically. This is independent of the storage model and can be added at any stage.

  • What if one customer loads the system more than the others?

    Introduce plan-based limits, move heavy operations into queues with quotas and, if needed, relocate the large customer to dedicated resources.