← Back to blog

Database-Per-Tenant: Why We Chose True Multi-Tenancy for Vectis

· Stoa Logistics
architecture engineering security

Database-Per-Tenant: Why We Chose True Multi-Tenancy for Vectis

When building a SaaS application, you have to decide how to isolate customer data. The two main approaches:

  1. Shared database with row-level filtering — All customers in one database, every table has a tenant_id column
  2. Database-per-tenant — Each customer gets their own database

Most SaaS products choose option 1. It’s simpler to build, easier to manage, and scales well for most use cases. We chose option 2 for Vectis. Here’s why.

The Row-Level Filtering Approach

In a shared database model, every query includes a tenant filter:

SELECT * FROM orders WHERE tenant_id = 'acme-corp' AND status = 'pending';

This works, but it has risks:

One bug exposes everyone’s data. Forget the WHERE tenant_id = ? clause in one query and you’re leaking data across tenants. Every developer, every code review, every query has to get this right.

Performance isolation is hard. One tenant running a heavy report can slow down everyone else. You can add query timeouts and resource limits, but you’re still sharing the same database engine.

Compliance gets complicated. Some customers want their data in specific regions. Some want the ability to export and delete everything. With a shared database, these requests require careful surgery.

Backups are all-or-nothing. You can’t easily restore one tenant’s data without affecting others.

The Database-Per-Tenant Approach

With database-per-tenant, each customer gets complete isolation:

-- Connected to acme-corp's database
SELECT * FROM orders WHERE status = 'pending';
-- No tenant_id needed - you're already in their database

Security by architecture. There’s no tenant_id to forget. The connection itself determines which data you see. A bug in your query logic can’t leak data across tenants because the data isn’t there.

Performance isolation. Heavy queries affect only that tenant’s database. You can even provision different database sizes for different customers.

Compliance is straightforward. Want to delete a customer’s data? Drop the database. Want to move them to EU region? Spin up a new database in Frankfurt and migrate.

Independent backups. Restore one tenant without touching others.

The Tradeoff: Operational Complexity

Database-per-tenant isn’t free. You’re managing potentially thousands of databases instead of one. This means:

  • More connection management
  • More complex migrations (run against every database)
  • More monitoring and alerting
  • Higher baseline costs (each database has overhead)

How We Made It Work: Neon Serverless PostgreSQL

The traditional database-per-tenant model was expensive because each database meant a running server. Even a small PostgreSQL instance costs ~$15/month. With 1,000 tenants, that’s $15,000/month just in database costs.

Neon changes this equation. It’s serverless PostgreSQL with:

  • Scale to zero — Databases that aren’t being used don’t cost anything
  • Instant provisioning — New database in milliseconds, not minutes
  • Branching — Create database copies for testing without full duplication
  • Per-tenant connection pooling — Efficient connection management built in

With Neon, we can provision a database for every tenant without the operational overhead or cost explosion.

The Implementation

When a new tenant signs up:

  1. Provision a new Neon database (< 1 second)
  2. Run migrations to create schema
  3. Store connection string in tenant registry
  4. Route all requests for that tenant to their database

The application layer handles connection routing:

async function getTenantConnection(tenantId: string): Promise<Database> {
  const tenant = await tenantRegistry.get(tenantId);
  return connectionPool.get(tenant.databaseUrl);
}

Every request includes tenant identification (from auth token), and we route to the appropriate database.

When Database-Per-Tenant Makes Sense

This architecture is worth the complexity if:

  • Data sensitivity is high — Financial data, health data, or anything where a leak is catastrophic
  • Compliance requirements vary — Different customers need different regions or retention policies
  • Performance isolation matters — Enterprise customers don’t want to share resources with everyone else
  • You’re building for 3PLs — They need complete separation between their clients

For a simple B2C SaaS with low-sensitivity data, shared database is probably fine. For an OMS handling business-critical order and inventory data? We think true isolation is worth it.


Vectis uses database-per-tenant architecture via Neon serverless PostgreSQL. See how it works.

Ready to simplify your operations?

See how Vectis can help your team.

Request a demo