The migration had stalled on one line of SQL. A single command. ALTER TABLE ADD COLUMN. The new column was the smallest change in scope, yet it carried the biggest risk.
A new column is rarely about storing more data. It changes schema contracts. It shifts query plans. It alters assumptions baked into the application. If the database is in production, that change now touches active traffic, indexes, replication lag, and lock times.
Before adding a new column, define its purpose. Is it nullable? Does it have a default value? Will it replace an existing field or extend it? Map the exact reads and writes it will affect. If it requires backfilling data, decide whether to run it in a single transaction, batch process, or via background jobs.
Assess the database engine’s behavior. In Postgres, adding a nullable column without a default is instant, but with a default, it can lock the table for the duration of the update. In MySQL, the process can trigger a table copy depending on storage engine and configuration. In distributed databases, the schema change may require versioned migrations to keep nodes in sync.