In most systems, adding a new column sounds simple. In reality, migrations can lock tables, block writes, and risk outages. The right approach keeps production fast, safe, and consistent.
A new column starts in the schema. Define the column with the correct type and constraints. Use defaults sparingly; they can trigger full table rewrites. For massive datasets, create the column as nullable to avoid long locks. Then backfill data in batches, using transactions small enough to avoid impacting replication or causing deadlocks.
Coordinate schema changes with deployment. If application code writes to the new column before it exists, it will break. If code reads from it too soon, it will fail. Use feature flags or multi-step deploys. First, add the column. Then deploy code to populate it. Only then make it required.
Performance matters. An unused column is harmless, but a badly indexed column can slow the entire database. Add indexes after the backfill is complete. Rebuild statistics so the query planner has accurate data.