How to Roll Out Migrations Across Separate Tenant Databases

using a separate database for each tenant does not make schema updates automatic. A normal application migration usually updates the central database only. Tenant migrations must be run across every tenant database as a separate deployment step.

Why choose a database per tenant?

This model gives each customer a separate data store. It can reduce the risk of accidental cross-tenant queries and make customer-specific backup, restore, export, or deletion easier.

The tradeoff is operational work. Every new tenant needs a database, and every schema change must reach all existing tenant databases.

Central and tenant migrations are different

A multitenant Laravel application commonly has two groups of tables:

  1. Central tables store tenant records, domains, and shared application data.

  2. Tenant tables store each tenant’s business data in its own database.

Running the normal migration command updates the central database. Tenant-aware tooling must switch to each tenant database and run the tenant migrations there.

A practical rollout process

  1. Keep tenant migrations in a dedicated migration directory.
  2. Deploy code that can temporarily work with both the old and new schema.

  3. Run the tenant migration command across all tenant databases.

  4. Record success or failure for each tenant and retry only failed tenants.

  5. Remove old columns or compatibility code in a later release.

For example, a tenant-aware package may provide a command such as:

php artisan tenants:migrate

The exact command depends on the package, but the principle is the same: the migration runner must select each tenant database before applying the schema change.

Common mistakes

Problem: only the central database changes.
Cause: the normal migration command was used.
Fix: add the tenant migration command to the deployment process.

Problem: some tenants remain on an old schema.
Cause: one failure stopped the whole rollout or was not recorded.
Fix: track migration status per tenant and support safe retries.

Problem: users see errors during a long rollout.
Cause: new code requires the new column before every tenant is migrated.
Fix: use backward-compatible, expand-then-contract changes.

When a shared database may be simpler

A shared database with a tenant identifier can be easier and cheaper for a very large number of small tenants. A database per tenant is more attractive when isolation and per-customer database operations matter more than operational simplicity.

Separate retries from rollback

A migration can partially change a database before failing, depending on the database and operation. Record the failed tenant and inspect its schema before rerunning or rolling back. Trial the rollout on a representative tenant backup and confirm that both old and new application code tolerate the transition.

Separate databases provide strong isolation, but schema rollout becomes a fleet operation. The concrete next step is to make tenant migration status and retries part of the deployment checklist.

Leave a Reply