Databases6 min read
Running Database Migrations on a Live System Without Downtime
The migration itself is rarely the risk. Locking a large table mid-traffic, or a schema that isn't backwards-compatible for a moment, is.
Tanjil Ahmed
Lead Software Engineer · Notionhive
A migration that runs fine on a development database with a thousand rows can lock a production table with fifty million rows for minutes, during which every write to that table queues up behind it. The safe-migration discipline exists entirely to prevent that gap between dev and production reality.
- Adding a nullable column is fast and safe on every major database; adding a NOT NULL column with a default can rewrite the whole table.
- Backfill data in small batches over time, never in a single migration transaction on a large table.
- Add an index concurrently (Postgres) or with `pt-online-schema-change` (MySQL) rather than a blocking index build.
- Deploy code that can handle both old and new schema before running a migration that removes the old shape entirely.
None of this is exotic once it's a habit — it's the expand-then-contract pattern applied consistently, and it's the difference between a migration nobody notices and a migration that becomes an incident report.
A migration that works on your laptop's database has told you nothing about what it will do to fifty million production rows.
