· Architecture  · 2 min read

Foundations: Understanding Multitenancy in SaaS

Serving multiple clients from a single codebase isn't magic. It's a careful choice between database, schema, and column isolation.

Serving multiple clients from a single codebase isn't magic. It's a careful choice between database, schema, and column isolation.

Your startup just signed its second enterprise client. Great! But now they are asking: “Is my data visible to Client A?”

Multitenancy is the architecture where a single instance of software serves multiple tenants (customers). It is the economic engine of SaaS, allowing you to maintain one codebase while serving thousands of customers independently.

The Three Models of Isolation

How do we keep Client A’s data away from Client B? There are three main strategies, ranging from “safest but expensive” to “cheapest but risky”.

1. Database-per-Tenant (Silo)

Every customer gets their own physical database.

  • Pros: Ultimate security. Data is physically separated. restoring Client A’s backup doesn’t affect Client B.
  • Cons: Expensive. Maintaining 1,000 databases is a DevOps nightmare.
  • Use Case: Banks, Government, Healthcare.

2. Schema-per-Tenant (Bridge)

One physical database, but each customer gets their own Schema (namespace).

  • Pros: Good balance. Data is logically separated. Manageable cost.
  • Cons: Tools like Liquibase need to run migration scripts across every schema for every deployment.
  • Use Case: B2B Enterprise SaaS.

3. Column-per-Tenant (Pool)

One database, one schema, one table. Every table has a tenant_id column.

  • Pros: Maximum efficiency and lowest cost.
  • Cons: High Risk. A developer forgetting WHERE tenant_id = ? in a SQL query results in a massive data leak.
  • Use Case: B2C apps (Spotify, Netflix), High-volume/Low-risk data.

Implementing the “Pool” Model Safely

In the fintech world, we often use a hybrid, but if you use the Pool model (Column separation), you must automate the filtering.

Using frameworks like Hibernate Filters or Spring Data JPA, you can enforce that every query automatically appends the tenant_id predicate based on the logged-in user’s context.

// Never trust manual queries
// Bad:
repository.findAll(); 

// Good (Automatic Injection):
// The framework intercepts the query and rewrites it to:
// SELECT * FROM accounts WHERE tenant_id = 'client_A'

Conclusion

Multitenancy is a spectrum. The “right” choice depends entirely on your diverse requirements for Security, Cost, and Performance. Understanding these trade-offs is what separates a junior developer from a software architect.

Back to Blog

Related Posts

View All Posts »