The database was slow, and the product team needed a new column before the next push.
Adding a new column sounds simple. It can break production if handled poorly. In relational databases, a new column changes the schema, updates indexes, and can trigger locks. If the table holds millions of rows, writes may stall and queries may fail.
Always start with the impact. Ask if the new column is nullable, non-nullable with a default, or computed. Each choice changes how the migration behaves. Non-nullable columns with no default require rewriting every row. This can lock the table and block other operations. Nullable columns are safer to deploy first and backfill later.
Plan migrations in small, reversible steps. First, add the nullable new column. Second, backfill data in batches. Third, enforce constraints and indexes after the data is ready. Use feature flags to hide incomplete data from the application until the migration finishes.
If you work with distributed systems, remember that schema changes must be backward compatible during rollout. A new column should not break old code paths. Deploy server changes that read and ignore the column before you write new values to it. Only after all services understand the column should you enforce stricter rules.