포스트모템: 20 (새 탭에서 열림)

2020년 4월 29일 발생한 Figma의 서비스 장애는 메인 데이터베이스인 PostgreSQL의 메모리 부족(OOM)으로 인해 발생했습니다. 근본 원인은 시스템 카탈로그 테이블인 pg_attribute의 비정상적인 팽창(Bloat)이었으며, 이는 장기 실행 트랜잭션이 데이터 정리를 방해하면서 발생한 연쇄적인 성능 저하의 결과였습니다. 결과적으로 모든 데이터베이스 연결이 지연되고 메모리가 고갈되면서 전체 서비스가 중단되는 사태에 이르렀습니다.

시스템 카탈로그(pg_attribute)의 비정상적 팽창

  • PostgreSQL에서 테이블 열(column) 정보를 저장하는 pg_attribute 테이블이 약 64GB까지 비대해지는 현상이 발생했습니다.
  • 모든 SQL 쿼리는 실행 계획을 세울 때 이 시스템 카탈로그를 참조해야 하므로, 이 테이블의 성능 저하는 곧 모든 DB 작업의 지연으로 직결되었습니다.
  • 평소 1ms 미만이던 메타데이터 조회 시간이 수 초 단위로 늘어났고, 이는 데이터베이스 연결(Connection)의 급증과 메모리 점유율 상승으로 이어졌습니다.

VACUUM 작동 불능과 장기 실행 트랜잭션

  • PostgreSQL의 가비지 컬렉션 역할을 하는 VACUUM 프로세스가 pg_attribute 내의 불필요한 행(dead tuples)을 정리하지 못하는 상태였습니다.
  • 장애 발생 당시 며칠 동안 유지되고 있던 '장기 실행 트랜잭션(Long-lived transaction)'이 원인이었습니다. 이 트랜잭션이 특정 시점의 데이터 스냅샷을 붙잡고 있어, VACUUM이 그 이후에 생성된 쓰레기 데이터를 삭제할 수 없게 방해했습니다.
  • 이 상태에서 대량의 임시 테이블 생성 및 삭제 작업이 반복되자, 정리되지 못한 행들이 기하급수적으로 쌓이며 테이블 크기가 폭발적으로 증가했습니다.

장애 전파 및 복구 과정

  • 팽창된 시스템 테이블로 인해 쿼리 분석 단계에서 과도한 메모리가 사용되었고, 결국 Primary DB 인스턴스가 OOM(Out of Memory) 상태에 빠져 모든 서비스를 중단시켰습니다.
  • Figma 팀은 즉각적인 가용성 확보를 위해 DB 인스턴스를 더 높은 메모리 사양으로 수직 확장(Scale-up)했습니다.
  • 이후 VACUUM의 정상 작동을 가로막던 오래된 트랜잭션들을 강제로 종료하고, 시스템 테이블에 대한 REINDEX를 수행하여 비대해진 인덱스를 정리함으로써 성능을 정상화했습니다.

재발 방지를 위한 권장 사항

데이터베이스의 안정성을 유지하기 위해서는 사용자 데이터뿐만 아니라 시스템 메타데이터의 상태를 정기적으로 점검해야 합니다. 특히 장기 실행 트랜잭션은 VACUUM 효율을 떨어뜨려 DB 전체에 치명적인 영향을 줄 수 있으므로, 특정 시간(예: 5분) 이상 지속되는 트랜잭션을 자동으로 종료하는 설정(idle_in_transaction_session_timeout)을 도입하고 시스템 테이블 크기에 대한 모니터링 알람을 구축하는 것이 권장됩니다.