피드로 돌아가기
We Deleted 10 Real Users with a Test-Cleanup Script — RCA
Dev.toDev.to
Database

ID 범위 기반 삭제로 인한 실사용자 10명 유실 및 복구 실패 사례

We Deleted 10 Real Users with a Test-Cleanup Script — RCA

sm1ck2026년 5월 28일9intermediate

Context

Telegram ID(양수)와 OAuth ID(음수)를 분리하기 위해 Postgres Sequence 기반의 음수 ID 할당 구조를 채택함. 테스트 데이터 정리를 위해 특정 ID 범위(Range)를 삭제하는 스크립트를 운용하며 실사용자와 테스트 계정의 ID 영역이 중첩되는 설계 결함을 가짐.

Technical Solution

  • ID 범위 기반 삭제에서 명시적 속성 필터링(auth_source = 'test') 방식으로 전환하여 데이터 격리 보장
  • setval(GREATEST(-MIN(id), currval)) 로직으로 인한 Sequence 전진과 테스트 계정 수동 삽입 간의 상호작용 제거
  • ON CONFLICT DO UPDATE를 통한 무분별한 데이터 덮어쓰기 방지 및 데이터 무결성 검증 단계 추가
  • RPO(Recovery Point Objective) 기반의 백업 체계 재설계 및 Hourly Logical Dump 도입
  • 백업 파일의 유효성 검증을 위한 월 단위 Restore Rehearsal 프로세스 구축
  • 파괴적 쿼리 실행 전 Dry-run 및 예상 삭제 건수 검증(Assertion) 단계 의무화

- 데이터 구분 시 ID 범위(Range)가 아닌 명시적 속성(Attribute) 필드를 사용하고 인덱스를 적용할 것 - 파괴적인 데이터 정리 스크립트는 반드시 Staging 환경에서 실제 데이터 기반의 Dry-run을 수행할 것 - 백업 주기 설정 전 비즈니스 허용 가능 데이터 손실 시간(RPO)을 먼저 정의할 것 - 복구 테스트를 거치지 않은 백업은 백업이 아니라는 전제로 정기적인 복구 훈련을 실시할 것

원문 읽기