The migration failed halfway through. The logs showed a single error: column does not exist. You check the schema. You check the code. The truth is obvious. You forgot to add the new column.
Adding a new column should be simple. In SQL, it is. You run:
ALTER TABLE users ADD COLUMN last_login TIMESTAMP;
The database accepts it. The column exists. But the job is not done.
In production, a new column is more than a schema change. It is a contract change. The code must know about it. Old queries must not break. Data backfills must happen in a safe and efficient way.
When you add a new column to a large table, think about locking. Even an ALTER TABLE that seems safe can cause downtime if the database engine must rewrite the whole table. For PostgreSQL, some column additions are instant; others force a rewrite. Know which is which before you run the command.
Consider NULL defaults versus populated defaults. Setting a default value at creation time might cause a table rewrite in some engines. For massive datasets, that is a risk. One pattern is:
- Add the new column as nullable.
- Deploy the code that can handle NULL.
- Backfill in batches.
- Add constraints or defaults after backfill completes.
Migrations should be part of your deployment pipeline. Automated checks can catch missing new column references before they hit production. Use feature flags to gate the code that relies on the new column until the data is ready.
In analytics systems, adding a new column to event tables can be handled with schema evolution if your storage supports it, like in BigQuery or Iceberg. Even then, query logic must adapt to handle absent fields in historical data.
Mistakes with new columns are common in schema evolution. They can cause silent data loss or unexpected downtime. The fix is process discipline: clear migration steps, awareness of engine-specific behavior, and staged rollouts.
If you need a place to experiment with new column changes and see the results instantly, try it at hoop.dev. You can build it, ship it, and watch it run in minutes.