# Multi-tenancy in PostgreSQL: separate instance, schema, or row-level security?

Every SaaS built on PostgreSQL has to answer this before it can be sized, priced or audited. There are three usual candidates, they are not equally good, and the right answer depends less on your engineering taste than on who has to believe it.

Our recommendation for regulated data, stated up front: **a separate PostgreSQL instance per major customer, with schema isolation for the tenants underneath.** The rest of this page explains why, and what it costs you, because it is not free.

## The three models

### Row-level security

One database, one schema, one set of tables. Every row carries a tenant identifier and PostgreSQL's [row-level security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) policies filter what each session may see.

It is the cheapest model to run and the most demanding to prove. Correctness depends on every session setting the right context, on every policy being right, and on no code path bypassing it. All three are properties of your application, not of the database boundary.

That distinction is what matters in an audit. An auditor cannot verify row-level security by looking at the database. They have to reason about your application code, and so do you, every time you add a query path. It is a defensible choice for tenants who are not separately regulated. It is the hardest of the three to defend when your tenants are insurers or banks.

### Schema isolation

One instance, one database, one schema per tenant. Tables are physically separate, a connection can be scoped to a schema, and a mistake in application code is far less likely to return another tenant's rows.

It gives you real separation of data with one instance to operate, and it is a good fit for many tenants of moderate value. What it does not give you is separation of everything around the data. Tenants share an instance, so they share its resources, its maintenance window, its major version upgrade and its point-in-time recovery timeline. Restoring one tenant to last Tuesday means restoring the instance.

### Separate instance per tenant

Each customer gets their own PostgreSQL instance with its own credentials, its own backups, its own restore timeline and its own upgrade schedule.

This is the model that survives contact with a regulated customer's auditor, because the boundary is one they can see. Separation is a fact about the deployment rather than a claim about your code. Concretely, it gives you:

- **Credentials per tenant.** A leaked connection string exposes one customer.
- **Backup and restore per tenant.** You can restore one customer to a point in time without touching anyone else, which is the difference between a contained incident and an outage for everyone.
- **A clean audit scope.** When a customer's auditor asks what else runs in the database holding their data, the answer is "nothing".
- **A clean exit.** Offboarding is a dump and a deletion, not a filtered extract you have to prove was complete.

## What it costs

A separate instance per customer multiplies. Each one carries its own service fee and its own storage, so **your isolation model is also your scaling model**. Adding a large customer adds a recurring cost, and that cost belongs in your own pricing before you sign them, not after.

This is the honest trade-off. Row-level security scales to many tenants cheaply and is hard to prove. Separate instances are easy to prove and scale linearly in cost. Anyone who tells you a model is strictly better on both axes is selling you something.

## The shape we usually end up recommending

Most Swiss B2B SaaS products are not flat. They have a small number of large customers, each with many users, and often a hierarchy: your platform, then a major customer, then that customer's own departments or subsidiaries.

That maps onto a hybrid, and it is the same shape as the commercial reality:

| Level | Isolation | Why |
|-------|-----------|-----|
| Major customer | Separate instance | Their auditor is the one asking, and their contract is the one at risk |
| Tenants inside that customer | Schema per tenant | Same legal entity, same data controller, separation for hygiene rather than for a regulator |
| Individual users | Application authorization | Not a database concern |

The boundary sits where the legal responsibility changes. That is a rule you can explain to an auditor in one sentence, which is worth more than a marginally cheaper design you have to defend in ten.

## What this looks like on managed PostgreSQL

VSHN Managed PostgreSQL runs each instance with high availability as a primary and replica with automatic failover, point-in-time recovery, and encryption at rest. Instances run on your own Kubernetes cluster, so adding an instance for a new customer adds its service fee and its storage without adding a separate cluster to operate.

Backups are part of the service. Compute and memory come from the cluster you already run, which means the per-customer cost of this model is more predictable than it looks at first.

If you are working out what your isolation choice does to your unit economics, book a call and we will price the shape you are considering.

## Related

- [What is PostgreSQL?](/what-is-postgresql/) if you are still choosing a database
- [Comparison](/comparison/) of managed PostgreSQL options in Switzerland
- [Sovereignty](/sovereignty/) on jurisdiction and data residency
