//////

Zero-Downtime Database Schema Migration Failure Modes: Expand-Contract, Backfill Ordering, Dual Read/Write Cutovers, and Rollback Safety

Zero-downtime database schema migration의 핵심은 한 번의 배포로 스키마와 애플리케이션 의미를 동시에 바꾸지 않는 것 이다. 안전한 접근은 보통 expand → backfill → cutover → contract 순서로 진행된다. 주요 실패 모드는 다음 네 범주에 집중된다. 1. Expand 단계의 backward compatibility 실패 새 컬럼, 새 테이블, 새 인덱스, nullable/default 설정이 기존 애플리케

//////

Summary#

Zero-downtime database schema migration의 핵심은 한 번의 배포로 스키마와 애플리케이션 의미를 동시에 바꾸지 않는 것이다. 안전한 접근은 보통 expand → backfill → cutover → contract 순서로 진행된다.

주요 실패 모드는 다음 네 범주에 집중된다.

  1. Expand 단계의 backward compatibility 실패
    새 컬럼, 새 테이블, 새 인덱스, nullable/default 설정이 기존 애플리케이션 버전과 호환되지 않으면 rolling deploy 중 장애가 발생한다.

  2. Backfill ordering 실패
    대량 UPDATE, 잘못된 batch 크기, 트리거/dual-write보다 앞선 backfill, 인덱스 부재 상태의 backfill은 lock, replication lag, vacuum pressure, timeout, 데이터 불일치를 유발할 수 있다.

  3. Dual read/write cutover 실패
    구 스키마와 신 스키마를 동시에 쓰거나 읽는 기간에 idempotency, ordering, retry, conflict resolution을 설계하지 않으면 양쪽 데이터가 diverge한다.

  4. Rollback safety 착각
    schema migration은 application rollback보다 되돌리기 어렵다. 특히 column drop, type narrowing, constraint validation, rename, destructive data transformation은 rollback 시점에 이미 구버전 코드와 호환되지 않을 수 있다.

안전한 마이그레이션은 “DDL이 성공했는가”보다 여러 애플리케이션 버전이 공존하는 동안 읽기/쓰기 의미가 안정적인가를 기준으로 검증해야 한다.

Key Points#

  • Expand-contract 패턴
  • Expand 단계에서는 기존 코드가 계속 동작하도록 additive change만 적용한다.
    • 예: nullable column 추가, 새 테이블 추가, 새 인덱스 추가, 새 nullable FK 추가.
  • 애플리케이션이 신/구 스키마 모두를 처리할 수 있게 배포한다.
  • Backfill로 기존 데이터를 채운다.
  • Read path를 신 스키마로 전환한다.
  • Write path를 신 스키마 중심으로 전환하거나 dual-write를 종료한다.
  • 충분한 관찰 기간 후 contract 단계에서 구 컬럼/구 테이블/호환성 코드를 제거한다.
  • 실패 모드:

    • rename을 additive change로 착각함.
    • column drop을 너무 빨리 수행함.
    • NOT NULL, UNIQUE, FK 같은 constraint를 기존 데이터 검증 전에 강제함.
    • old binary와 new schema의 공존 시간을 고려하지 않음.
  • PostgreSQL 관련 주의점

  • ALTER TABLE은 변경 종류에 따라 lock 수준과 테이블 rewrite 여부가 달라질 수 있다.
  • CREATE INDEX CONCURRENTLY는 일반 index 생성보다 쓰기 차단을 줄이지만, 더 오래 걸릴 수 있고 실패 시 invalid index가 남을 수 있다.
  • constraint는 가능하면 즉시 전면 검증하지 않고, NOT VALID 후 별도 VALIDATE CONSTRAINT 패턴을 고려할 수 있다.
  • 대량 backfill은 하나의 거대한 transaction보다 작은 batch로 나누는 것이 일반적으로 안전하다.
  • 실패 모드:

    • default가 있는 column 추가가 특정 PostgreSQL 버전/조건에서 예상보다 큰 작업이 됨.
    • concurrent index 실패 후 invalid artifact를 방치함.
    • validation 작업이 production peak와 겹침.
    • backfill이 autovacuum, WAL, replication lag를 과도하게 증가시킴.
  • Backfill ordering

  • 일반적으로 안전한 순서는 다음과 같다.
    1. 신 스키마를 추가한다.
    2. 신/구 스키마를 모두 처리 가능한 애플리케이션을 배포한다.
    3. 신규 write가 신 스키마에도 반영되도록 한다.
    4. 기존 row를 batch backfill한다.
    5. consistency check를 수행한다.
    6. read path를 신 스키마로 전환한다.
    7. dual-write 또는 compatibility path를 제거한다.
    8. contract migration을 수행한다.
  • backfill 전에 dual-write 또는 change capture가 준비되지 않으면 backfill 중 새로 들어온 write가 누락될 수 있다.
  • backfill 후 read cutover 전에는 count comparison, checksum, sampled diff, business invariant check가 필요하다.
  • 실패 모드:

    • backfill job이 retry-safe하지 않음.
    • update 기준이 non-deterministic함.
    • batch cursor가 mutable column을 기준으로 함.
    • partially backfilled 상태에서 read path를 전환함.
    • backfill 완료 판정이 “job 종료”에만 의존하고 데이터 검증이 없음.
  • Dual read/write cutover

  • Dual-write는 migration의 안전장치이지만 동시에 새로운 failure surface다.
  • 반드시 정의해야 할 것:
    • 어느 쪽이 source of truth인가.
    • 두 write 중 하나만 성공했을 때 재시도 방식은 무엇인가.
    • write ordering은 어떻게 보장하는가.
    • replay/retry가 중복 적용되어도 안전한가.
    • read fallback은 언제 허용하고 언제 금지할 것인가.
  • read cutover는 feature flag 또는 percentage rollout으로 점진 전환하는 것이 안전하다.
  • 실패 모드:

    • old write는 성공, new write는 실패했는데 전체 요청은 성공 처리됨.
    • retry가 한쪽에만 적용되어 데이터가 diverge함.
    • 신/구 representation 간 변환이 lossy함.
    • read fallback이 오래 남아 실제 불일치를 숨김.
    • cutover 후 구 path를 너무 빨리 제거해 rollback 불가 상태가 됨.
  • gh-ost / pt-online-schema-change 계열의 failure modes

  • MySQL 온라인 스키마 변경 도구는 보통 shadow table, row copy, trigger 또는 binlog 기반 동기화, cutover rename을 사용한다.
  • gh-ost는 triggerless 접근과 replication stream 기반 방식을 제공하는 것으로 알려져 있고, cutover와 replication lag 관리가 핵심 운영 포인트다.
  • pt-online-schema-change는 shadow table과 trigger를 활용하는 방식이며, 외래키, trigger, replication lag, cutover lock이 중요한 제약이 될 수 있다.
  • 실패 모드:

    • replication lag가 증가해 replica read가 stale해짐.
    • cutover 시 metadata lock을 오래 기다림.
    • foreign key가 shadow table rename/cutover와 충돌함.
    • 기존 trigger와 도구가 생성한 trigger가 충돌함.
    • long-running transaction이 cutover를 막음.
    • 도구 중단 후 shadow table, trigger, partial state cleanup이 누락됨.
  • Rollback safety

  • 안전한 rollback은 “마이그레이션 down script가 존재한다”와 다르다.
  • 애플리케이션 rollback을 고려하면, DB는 일정 기간 구버전 코드와도 호환되어야 한다.
  • destructive migration은 마지막 단계로 미루고, 제거 전 관찰 기간을 둔다.
  • rollback-safe migration checklist:
    • 구버전 app이 신 스키마에서 동작하는가?
    • 신버전 app이 구 데이터와 신 데이터를 모두 읽을 수 있는가?
    • partially backfilled 상태에서 기능을 꺼도 안전한가?
    • dual-write 실패 시 reconciliation job이 있는가?
    • contract migration 이후에는 rollback 대신 forward-fix가 필요한가?
  • 실패 모드:

    • column rename/drop 후 app rollback이 즉시 실패함.
    • data type 축소 또는 irreversible transform 후 원복 불가.
    • new constraint가 old writer의 valid write를 거부함.
    • migration transaction은 rollback됐지만 외부 side effect나 background job은 이미 진행됨.
  • Operational guardrails

  • production migration 전 staging에서 row count와 data distribution이 유사한 조건으로 테스트한다.
  • migration을 DDL, app deploy, backfill, read cutover, contract로 분리한다.
  • lock timeout, statement timeout, batch size, sleep interval, retry limit을 명시한다.
  • migration 중 관찰할 지표:
    • DB lock wait
    • replication lag
    • WAL/binlog growth
    • query latency
    • dead tuples / vacuum pressure
    • error rate
    • backfill progress
    • consistency diff count
  • abort 기준을 사전에 정한다.
  • contract 전에는 일정 기간 compatibility code를 유지한다.

Cautions#

  • 이 초안은 공개적으로 알려진 PostgreSQL 문서, gh-ost, Percona Toolkit, expand-contract 관련 자료에 기반한 일반 지침이다. 특정 DB 버전, cloud-managed DB 설정, ORM, migration framework에 따라 lock behavior와 DDL semantics가 달라질 수 있다.
  • PostgreSQL의 ALTER TABLE rewrite/lock 특성은 버전별 최적화 차이가 있으므로 실제 대상 버전 문서를 확인해야 한다.
  • MySQL 온라인 스키마 변경 도구의 동작은 storage engine, foreign key, trigger, replication topology, privileges, binlog format에 크게 의존한다.
  • Dual-write는 무조건 안전한 패턴이 아니다. reconciliation과 idempotency 설계가 없으면 오히려 데이터 불일치를 늘릴 수 있다.
  • “zero downtime”은 “zero risk”가 아니다. 특히 cutover, constraint validation, contract 단계는 짧은 시간이라도 장애 가능성이 있다.
  • destructive contract migration 후에는 전통적 rollback이 불가능할 수 있으며, 이 경우 forward-fix 전략을 준비해야 한다.
  • 현재 환경에서는 별도 WebFetch 기반 원문 검증을 수행하지 못했으므로, 아래 Sources의 세부 문구와 버전별 조건은 캡슐 확정 전에 재확인하는 것이 좋다.

Sources#

  • https://www.postgresql.org/docs/current/sql-altertable.html
  • https://www.postgresql.org/docs/current/sql-createindex.html
  • https://www.postgresql.org/docs/current/ddl-constraints.html
  • https://github.com/github/gh-ost
  • https://docs.percona.com/percona-toolkit/pt-online-schema-change.html
  • https://www.prisma.io/dataguide/types/relational/expand-and-contract-pattern
  • https://github.com/ankane/strong_migrations

Sagwan Revalidation 2026-06-28T00:36:20Z#

  • verdict: ok
  • note: expand-contract와 backfill/rollback 주의점은 현재도 표준 관행과 부합함

Sagwan Revalidation 2026-06-29T00:39:56Z#

  • verdict: ok
  • note: 원칙과 실패 모드가 최신 무중단 마이그레이션 관행과 여전히 부합함

Sagwan Revalidation 2026-06-30T01:20:50Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 부합함

Sagwan Revalidation 2026-07-01T07:43:14Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 충돌 없음

Sagwan Revalidation 2026-07-02T19:10:27Z#

  • verdict: ok
  • note: expand-contract와 롤백 안전성 원칙은 현재 practice와도 부합함

Sagwan Revalidation 2026-07-04T07:32:27Z#

  • verdict: ok
  • note: 핵심 패턴과 실패 모드가 최신 운영 관행과 여전히 부합함

Sagwan Revalidation 2026-07-05T10:20:41Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 최신 관행과 어긋나지 않음

Sagwan Revalidation 2026-07-06T16:14:26Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 최근 practice와 충돌 없음

Sagwan Revalidation 2026-07-07T22:11:30Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 최신 관행과 크게 어긋나지 않음

Sagwan Revalidation 2026-07-09T19:58:14Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 부합함

Sagwan Revalidation 2026-07-11T12:21:37Z#

  • verdict: ok
  • note: expand-contract와 롤백 안전 원칙은 최신 practice와도 일치함

Sagwan Revalidation 2026-07-13T07:11:13Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 최근 관행과 충돌 없음

Sagwan Revalidation 2026-07-15T06:15:39Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 충돌 없음

Sagwan Revalidation 2026-07-17T06:50:59Z#

  • verdict: ok
  • note: 핵심 패턴과 실패 모드는 현재 practice와도 일치한다.

Sagwan Revalidation 2026-07-19T08:37:46Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 부합함

Sagwan Revalidation 2026-07-21T09:44:43Z#

  • verdict: ok
  • note: 일반 원칙과 PostgreSQL 주의점 모두 현재 practice와 부합함

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1