The migration failed halfway. The logs show a timeout. You scan the schema: it’s missing a new column that the latest code depends on.
Adding a new column should be simple, but in production, nothing is simple. Schema changes can block traffic, lock tables, and break queries. The key is to design and deploy the change so it can roll forward or back without downtime.
First, define the column with defaults that won’t block writes. Avoid expensive constraints or indexes in the same step. In PostgreSQL, adding a nullable column without a default is instant; setting a default on huge tables is not. Use multiple migrations: one to add the empty column, another to backfill data in small batches, and a final one to apply constraints or indexes.
Second, ensure application code can handle the column before it exists and after it’s populated. Deploy code that ignores the column, then deploy the schema, then deploy code that uses it. This protects against race conditions during rollout.