The logs were clean. The service stayed up. The schema now had a new column.
Adding a new column looks simple. It is not. In production, schema changes carry risk. A single blocking lock can stall queries, cascade delays, and trigger timeouts down the stack. Every millisecond of downtime is public. Every index rebuild hits storage and I/O.
The first rule: know your database engine. PostgreSQL, MySQL, and others handle ALTER TABLE ADD COLUMN differently. Some execute it instantly for nullable columns without a default. Others rewrite the whole table if a default value is set. On large datasets, that rewrite is the bottleneck.
Reduce risk by adding the column nullable, without defaults, in one migration. Backfill data in batches. Then enforce constraints in a later, fast migration. This staged approach reduces lock time and keeps services responsive.