Safe database migrations in busy systems
Practical patterns we use to evolve schemas without blocking traffic or waking up the on-call.
Schema changes can be scarier than code deploys. These are the steps we take to keep migrations uneventful in production.
Prefer additive first
We add nullable columns, new indexes, or shadow tables before touching existing paths. Application code writes to both old and new shapes until we verify parity with background jobs.
Control the blast radius
- Run migrations in small batches with explicit timeouts.
- Use advisory locks or feature flags to pause high-risk write paths during delicate steps.
- Watch replication lag and buffer cache metrics in a dedicated migration dashboard.
Clean up with confidence
Once dual writes are stable, we flip reads to the new schema behind a feature flag. After a full traffic day without errors, we drop deprecated columns and remove the dual-write logic in a follow-up deploy.
Following this cadence keeps the database calm while the product keeps moving.