Multi-tenancy is the foundation of virtually every SaaS product. The term sounds abstract, but the question is concrete: how do you serve hundreds of customers on the same infrastructure without their data mixing together and without customer A's actions affecting customer B's experience?
This article covers the architecture choices required for this, the security risks you need to know, and how to organize this at scale in a Dutch hosting environment.
What multi-tenancy means in practice
In multi-tenancy, multiple customers (tenants) share the same application instance and infrastructure. They only see their own data, but the code processing that data is identical. This differs fundamentally from dedicated environments, where each customer has their own server or VM.
The benefits are significant. You maintain one codebase, roll out updates to all customers simultaneously, and share infrastructure costs. An application with a thousand tenants on shared infrastructure costs a fraction of what a thousand separate VMs would cost.
The challenges fall into three areas: data isolation, resource isolation, and tenant-specific configuration.
Data isolation: three models
How you store data determines your isolation profile. There are three common models, each with its own trade-offs:
Shared database, shared schema: all tenants in the same tables, separated by a tenant_id column. Maximum efficiency, lowest cost per tenant. Row-Level Security (RLS) in PostgreSQL is the most commonly used technique for this. The risk: a bug in your RLS definition exposes data from all tenants. This model requires solid test coverage on isolation logic.
Shared database, separate schema: each tenant gets their own schema within the same database. Better isolation, slightly higher overhead per tenant. Works well combined with database-level permissions. Practically achievable with up to several hundred tenants on a single database server.
Separate database per tenant: maximum isolation, simplest compliance story. Much higher costs and management overhead. Makes sense for enterprise customers with their own compliance requirements, or as part of a tiered pricing model where this is offered as a premium feature.
Multi-tenancy models compared
| Model | Isolation | Cost/tenant | Management | Suitable for |
|---|---|---|---|---|
| Shared schema | Low | Lowest | Simple | SMB, high scale |
| Separate schema | Medium | Average | Moderate | Mid-market |
| Separate database | High | Highest | Complex | Enterprise, regulated |
Resource isolation: preventing noisy neighbors
Data isolation is one thing. Resource isolation is another challenge. When one tenant runs a heavy query, it shouldn't affect the response times of other tenants. This is called the noisy neighbor problem, and it occurs in virtually every shared environment.
Solutions at the infrastructure level:
- Rate limiting at the API level: limit the number of requests per tenant per time period. Standard in API gateways like Kong or Nginx.
- Database connection pooling: PgBouncer or similar prevents one tenant from claiming all connections.
- Kubernetes resource quotas: with container-based deployments, you can limit CPU and memory per namespace.
- Queue-based processing: heavy tasks (exports, reports) go through a queue with separate workers, not inline via the API.
For larger tenants, it makes sense to offer dedicated resources as a premium option. This way you maintain the efficiency of multi-tenancy for smaller customers while closing enterprise deals with customers who need guarantees.
Authentication and authorization
In a multi-tenant system, every API call needs to know which tenant it's serving and whether the user has rights to the requested resource. This requires a well-designed IAM model.
Common approach: JWT tokens with a tenant_id claim. Each request contains a token that identifies the tenant and user role. Your middleware validates this token and injects the tenant context before the request reaches the business logic.
Pitfall: authorization logic scattered throughout the codebase instead of centralized. That leads to a leak sooner or later. Use a central authorization layer (Policy-Based Access Control or Attribute-Based Access Control) that's consistently enforced.
Scaling strategy by growth stage
A multi-tenant architecture scales differently than a single-tenant application. Most growing pains don't come from more tenants, but from a small group of tenants using disproportionately more resources.
Per-tenant monitoring is essential for this. You want to know which tenants generate the most database traffic, have the longest queries, and make the most API calls. Without those insights, you're reacting blindly to capacity problems.
When to take which scaling step?
Security: what can go wrong
The biggest security risks in multi-tenant applications aren't spectacular. They result from small mistakes in everyday code:
- A query that forgets to filter on tenant_id
- An API endpoint that retrieves objects by ID without ownership verification (Insecure Direct Object Reference)
- Shared caches where the cache key isn't tenant-specific
- Log files that mix tenant data from multiple customers
Penetration tests for multi-tenant applications specifically test for cross-tenant data leakage. Schedule this before you process sensitive customer data, not after.
Hosting in the Netherlands: what it adds
Multi-tenant architecture combined with hosting outside the EU creates GDPR risks. You're processing data from multiple customers who each have their own customers. That layering makes data sovereignty complex. Hosting in a Dutch data center with clear data processing agreements makes the compliance story transparent and verifiable, for you and for your customers.
Looking for scalable SaaS hosting? Check out our SaaS solutions.