Adding a new column should be simple. In practice, it often breaks production, creates schema drift, or leaves stale data. The root cause is almost always a gap between how the database evolves and how the application expects it to behave.
A new column alters the contract between code and data. It changes inserts, updates, and sometimes even queries that never touch it directly. If you add the column with a default value, the database must rewrite large datasets. Without a default, your application must handle nulls until backfills complete. Both paths have tradeoffs: blocking migrations, heavy locks, or deferred correctness.
When introducing a new column to a live system, zero-downtime techniques matter. Use migrations that add the column without constraints, then backfill in batches, then apply nullability or unique rules last. This pattern avoids long locks and lets you deploy code that tolerates the evolving schema.