Bir Web AjansBir Web Ajans

A database per tenant: not leaving isolation to chance in multi-tenant systems

In JournalPort and CongressPort every journal and every congress lives in its own database. Why we chose that path, and what it costs.

The most common approach to multi-tenancy is to keep every tenant in the same tables and add a tenant_id to each row. It is cheap and easy to set up. But isolation then depends on every query remembering the right filter. One forgotten WHERE clause can show one journal's review report to another journal's editor.

Drawing the boundary at the data layer

In Nova JournalPort, when a journal is approved the system provisions a dedicated MySQL database, runs migrations, seeds it and creates the owner account. Journal tables have no tenant_id column, because they do not need one. A request is bound to the journal resolved from its Host header and cannot see any other database for its lifetime.

Nova CongressPort applies the same principle on the Laravel side: every client congress runs in its own database and its own storage prefix, and an operator CRM provisions, suspends and re-domains tenants through a signed internal API.

The cost

  • Migrations run separately for every tenant, so we keep master and tenant migrations in separate sequences.
  • You cannot write one SQL query across tenants; portal-wide statistics are computed from a separate master catalogue.
  • Provisioning is a process, not an insert: it is managed through states such as PENDING, PROVISIONING, ACTIVE and FAILED.

Where rules like blind review, personal data and licence separation really matter, we find the cost worth paying. Isolation stops being a rule every line of code must remember and becomes the architecture itself.

The next system

Tell us howyou operate. We’ll buildthe system.