Skip to content

Data isolation

The contract

Every driver implements IsolationDriver:

MethodPurpose
provisionCreate the tenant's storage (schema/database/rows)
destroyDrop it cleanly (terminates active sessions first)
resetDrop and recreate (used by tenant:migrate:fresh)
connectOpen the runtime Lucid connection
disconnectClose it
connectionNameSynchronous resolver for the active query's connection
migrateRun migrations against this tenant's storage

The four drivers

DriverBest forNotes
schema-pgDefault. Most SaaS workloads.One PG schema per tenant. Strongest balance of isolation and operational cost.
database-pgEnterprise tenants needing OS-level isolation.One PG database per tenant. Requires CREATEDB. CREATE DATABASE outside transactions.
rowscope-pgLightweight workloads, large tenant counts, central reporting.Shared schema + tenant_id column. Strict scope by default.
sqlite-memoryTests only.In-process SQLite per tenant. Vanishes on process exit.

Choosing a driver

  • Strict isolation, easy backups, easy per-tenant restoreschema-pg. Nine out of ten cases.
  • Compliance-driven separation, cross-database JOIN not requireddatabase-pg. Higher operational cost: per-tenant pooling, backups, replication.
  • Hundreds of thousands of tiny tenants, central reporting required, write throughput mattersrowscope-pg. Watch out for forgotten scope; the strict mode catches most cases.
  • CI / unit testssqlite-memory. Don't ship to production.

Switching drivers

ts
// config/multitenancy.ts
export default defineConfig({
  isolation: {
    driver: 'schema-pg', // or 'database-pg' | 'rowscope-pg' | 'sqlite-memory'
    templateConnectionName: 'tenant',
  },
})

If you omit the isolation block entirely, the package defaults to { driver: 'schema-pg' } for v1 compatibility.

Was this page helpful?

Released under the MIT License.