The migration was done. The data looked clean. Then the request came in: add a new column.
Nothing freezes a release pipeline faster than a schema change. Adding a new column to a table seems simple. It almost never is. The hidden cost lies in production downtime, query degradation, broken migrations, and code paths that assume the old schema shape.
A new column can trigger a cascade. The ORM must know about it. The API contract may shift. Existing migrations need version control discipline. Scripts for backfilling values must avoid locking tables. Even a boolean with a default can grind writes to a halt if it forces a full table rewrite.
In SQL, adding a new column without defaults or constraints is usually fast. The real work is in the surrounding systems. For MySQL and Postgres, it’s common to add it as nullable first, then populate it in small batches, then add constraints. In distributed systems, you must handle rolling deployments where old code and new code overlap. This means feature flags for both reads and writes, careful ordering of migrations, and automated tests that verify both schema versions.