The migration hit production at 02:14, and the query that should have been fast was now locked. The reason was simple: adding a new column is never just adding a new column.
A new column changes your schema, touches indexes, and can create blocking locks that cascade under load. In high-traffic systems, a careless ALTER TABLE can freeze an entire service. The fix begins with knowing exactly what type of column addition you are making. Some databases can add nullable, default-less columns instantly. Others rewrite the entire table.
In PostgreSQL, adding a nullable column without a default is quick. Adding a column with a non-null default rewrites every row, which can take minutes or hours depending on size. In MySQL, ALGORITHM=INPLACE can make some additions non-blocking, but adding a NOT NULL column with a default often forces a full table copy. SQLite rewrites the table for most schema changes.
Plan new columns with a migration strategy that avoids downtime. Add columns as nullable first. Backfill data in small batches. Then add the constraint or default. Index creation should be deferred or done concurrently if supported, to avoid long locks. Use feature flags to gate application logic to the new column until all data is ready.