The schema was locked. The deadline was close. You needed a new column, and you needed it without breaking production.
Adding a new column seems simple. It isn’t. In a live system, every migration is a moving target. Reads and writes happen as you shape the database structure. Mistakes here cause downtime, consistency errors, or data loss. The right process avoids all three.
First, define the new column with a clear type and default value. Avoid implicit nulls unless your logic demands it. A default prevents backfill errors and simplifies queries after deployment.
Second, run migrations in phases. Phase one adds the new column as nullable or with a safe default. This step is low risk and executes fast. Phase two updates application code to write to both the old and new columns if you are migrating data across. Phase three backfills data in batches, never blocking traffic. Final phase switches reads to the new column and drops unused structures.