Engineering
Multi-tenant systems: design decisions that compound over time
May 4, 2026
Every platform Abrevon builds runs in a multi-tenant architecture. A single codebase serves multiple clients, each isolated from the others, each with their own data, configuration, and domain.
This creates leverage — improvements to the core benefit every client. It also creates risk — a mistake in isolation logic can expose one client's data to another. The decisions we make at architecture time determine which of these dominates.
Isolation strategies
There are three common approaches to tenant isolation: shared schema (a tenant_id column on every table), separate schemas within one database, and separate databases.
We use separate databases. Each client gets a dedicated Neon database, provisioned at onboarding. The connection string is encrypted and stored in our platform database — retrieved only when a request arrives for that tenant's domain.
The tradeoff is operational complexity. Migrations must be applied across every tenant database. Debugging requires knowing which database to inspect. Monitoring must aggregate across many databases.
We accept this tradeoff because the isolation guarantees are simpler to reason about. A query against one client's database cannot accidentally touch another's — not because we wrote careful WHERE clauses, but because there is nothing to accidentally cross.
Module-driven schema
Tenants do not all have the same schema. A salon needs appointment tables. A fleet operation needs vehicle and maintenance logs. A restaurant needs order and inventory tables.
We handle this through a module system. When a tenant is provisioned with a module, we run the corresponding SQL migration against their database. Only the tables that tenant's business needs exist in their database.
This keeps schemas small and coherent. It also makes the relationship between product capabilities and data structures explicit — which simplifies both implementation and debugging.
The compounding effect
Multi-tenant design decisions compound. A shortcut at the isolation layer means every subsequent feature must account for the possibility of cross-tenant data exposure. A shortcut at the schema layer means every migration becomes a negotiation between what different tenants need.
These shortcuts rarely cause obvious problems at launch. They cause subtle, expensive problems twelve months later, when the system is under real load with real data. This is why we make these decisions explicitly at the architecture stage — when changing them is cheap.