Databases & reliability · 2026

Your next migration will lock the users table.
Here is how to ship schema changes nobody notices.

Adding one NOT NULL column can freeze your whole app for minutes. The expand-and-contract pattern lets you change the schema of a live database without downtime.

Migrations as their own step.

On Belmo Pro, on-demand scripts run a migration or a backfill as a one-off job, separate from your web service, so a slow migration never sits inside your app's boot.

No credit card required 1 service free forever On-demand scripts on Pro EU and US regions
Frequently asked

Quick answers

Why did a simple migration take my app down?

Some schema changes need an exclusive lock. The migration waits for every running query on the table to finish, and while it waits, every new query queues behind it. On a busy table a two-second lock turns into a long outage as the connection pool fills up. On your laptop the table is tiny and nothing else is running, so it looks instant.

What is the expand and contract pattern?

A way to split a schema change into safe, separate deploys. Expand: add the new column or table without touching the old one. Migrate: backfill the data and ship code that uses the new shape. Contract: remove the old shape once nothing reads it. The schema always works with the code that is running.

How do I add a NOT NULL column without locking the table?

Add it as nullable, backfill existing rows in batches, then add a CHECK (col IS NOT NULL) NOT VALID constraint and run VALIDATE CONSTRAINT separately. The validation scans the table under a weaker lock that lets reads and writes continue.

Why use CREATE INDEX CONCURRENTLY?

A plain CREATE INDEX blocks writes to the table for the whole build, which can be minutes on a large table. The concurrent version builds in the background while writes continue. It is slower and cannot run inside a transaction, so check that your migration tool allows that.

Should database migrations run when the app boots?

No. Run them as their own step before the new code takes traffic. A slow migration inside the web process can fail the health check, and the platform may start restarting instances while the migration is still running.