Adding a new column to a production database should be fast, safe, and repeatable. Too often, it means downtime, failed migrations, or brittle scripts that break under scale. The right approach is to design the change so it can run in the background without blocking reads or writes.
First, define the new column with a default that doesn’t lock the table. In PostgreSQL, this can be done in two steps: add the column with NULL allowed, then backfill data in batches. Once complete, set the default and adjust constraints. This pattern removes lock contention and lets the operation roll out with zero interruption.
Indexing the new column should also be deferred. Create the index concurrently to avoid blocking queries. Test the migration in staging using representative production data to detect slow queries before they reach users. Monitor query plans and performance after deployment—especially if the new column appears in joins or filters.