A new column can seem simple, but in a live system it carries weight. Schema changes touch every layer: database, application code, and downstream consumers. A careless migration risks data loss, downtime, or growing replication lag. Speed matters, but safety matters more.
Start by defining the column precisely. Know its data type, nullability, default value, and indexing needs. Every choice affects performance and resource usage. Adding a nullable column is fast on most engines, but a non-null with a default can trigger a full rewrite of the table. Avoid wide columns unless they serve a clear purpose.
Plan the deployment in steps. First, add the new column without default values to avoid full copies of large datasets. Then backfill data in batches, using a controlled job or script that respects load. Only after the backfill should you enforce NOT NULL constraints or create indexes. This pattern minimizes locking and keeps replication healthy.
Check compatibility in the application layer. Even if the database has the column, the app must handle reads and writes without errors. Deploy code that writes to both old and new structures before switching reads, especially in systems with multiple services or queues. Feature flags can help isolate usage until the migration is complete.