Blue-Green + DB Migration Safety Pattern
Step-by-step strategy to reduce downtime risk by decoupling application transitions from schema changes

Introduction
Applications can be easily switched from Blue to Green, but a simple switch is not possible for databases. If schema changes and data changes occur together, service may be interrupted even after successful deployment if there is no rollback strategy. This article covers expand/contract patterns and conversion checkpoints to ensure DB migration safety.

Problem definition
The reason why failures are repeated in DB accompanying distribution is because code conversion and data conversion are not separated.
- Destructive schema changes are applied first, causing previous versions of the app to break immediately.
- Data loss occurs when traffic is switched without knowing the progress of the backfill operation.
- There is no two-way compatibility at the time of rollback, which increases recovery time.
The solution strategy is to enforce the order expand -> dual-write -> cutover -> contract. If the order is violated, it is difficult to guarantee safety.
Key concepts
| perspective | Design criteria | Verification points |
|---|---|---|
| schema level | Add compatible column | Whether the old version app works |
| data step | Backfill + Verification Report | Number of NULL/mismatches |
| Transition Stage | Toggle separate read/write paths | Error rate immediately after conversion |
| Cleanup Steps | Controlling the timing of old column removal | rollback possible time |
Blue-Green and DB migration should be combined into one deployment pipeline, but the data stage should be monitored independently.
Code Example 1: Expand Migration
ALTER TABLE orders
ADD COLUMN payment_status_v2 TEXT;
CREATE INDEX CONCURRENTLY idx_orders_payment_status_v2
ON orders (payment_status_v2);
-- 구버전 호환을 위해 기존 컬럼 유지
COMMENT ON COLUMN orders.payment_status_v2 IS 'new status field for v2 rollout';
Code example 2: Dual-write application code
export async function updatePaymentStatus(orderId: string, status: string) {
await db.tx(async (trx) => {
await trx.query(
"UPDATE orders SET payment_status = $2, payment_status_v2 = $2 WHERE id = $1",
[orderId, status],
);
});
}
Architecture flow
Tradeoffs
- Dual-write is safe, but it increases write path complexity and load.
- If the expand/contract period is long, the risk is low, but the development speed may slow down.
- Automating conversion checks increases quality, but requires initial pipeline construction costs.
Cleanup
Order management is key to DB safety in a Blue-Green environment. Separating schema compatibility, backfill verification, and staged cutover can significantly reduce the failure radius.
Image source
- Cover: source link
- License: CC BY-SA 3.0 / Author: Robert.Harker
- Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.