Online schema migration tools handle the database side of the change. But your application must also be written to handle the transition period — the window when both the old schema and the new schema might be in effect simultaneously.
The Dual-Write Window
During a migration, there is a period where:
- The old schema is live (before cutover).
- The new schema is live (after cutover).
If your application is deployed across 20 servers, some servers might still be running the old code (expecting the old schema) while others have been updated (expecting the new schema). This is normal during a rolling deployment.
Backward-Compatible Changes (Safe)
These changes can be made without coordinating application deployments:
| Change | Why It's Safe |
|---|---|
| Add a nullable column | Old code ignores it; new code uses it |
| Add a column with a default value | Old code ignores it; new code uses it |
| Add an index | Transparent to the application |
| Increase a VARCHAR length | Old data still fits |
Backward-Incompatible Changes (Dangerous)
These changes require careful sequencing:
| Change | Risk |
|---|---|
| Drop a column | Old code still tries to read/write it → error |
| Rename a column | Old code references the old name → error |
| Add a NOT NULL column without a default | Old code doesn't supply the value → constraint violation |
| Decrease a VARCHAR length | Existing data may not fit |
The Expand-Contract Pattern
For dangerous changes, use the expand-contract (also called parallel change) pattern:
- Expand: Add the new column alongside the old one. Deploy application code that writes to both columns.
- Migrate: Backfill the new column with data from the old column.
- Contract: Deploy application code that reads from the new column only. Then drop the old column in a separate migration.
This turns one risky migration into three safe ones, each independently deployable and rollback-able.