Incident Library

IL-0390 PostHog · 2025-11-11databaseaws

PostHog US Cloud 의 Persons Postgres 데이터베이스 쓰기가 크게 느려져 이벤트와 persons 수집이 최대 2일 지연됐다

2025년 11월 11일 16:02 UTC 부터 11월 14일 15:02 UTC 까지 PostHog 의 수집 처리 파이프라인 성능이 크게 떨어져, US 리전 모든 고객의 이벤트 처리가 최대 2일 지연됐다. 원인은 Person 정보를 저장하는 Postgres 데이터베이스가 person 속성을 담는 JSONb 열과 관련해 전에 겪은 적 없는 Postgres 한계에 닿은 것이었다. PostgreSQL 은 압축 뒤 2KB 를 넘는 큰 열 값을 TOAST 테이블이라는 별도 테이블에 저장하고, 옮긴 값마다 약 40억 개 크기의 32비트 공간에서 고유한 OID 를 하나씩 할당한다. OID 는 객체 식별자이고, 전역 카운터에서 나오며 40억 개마다 한 바퀴 돈다. 이미 쓴 값이 나오면 Postgres 는 다음 값으로 다시 시도한다. PostHog 의 Persons 테이블은 properties 열이 자주 2KB 를 넘어 TOAST 값이 아주 많았다. 쓴 OID 가 한계에 가까워지자 INSERT 나 UPDATE 한 건마다 비어 있는 OID 를 찾느라 엄청난 양을 읽게 됐다. 쓰기 쿼리 하나의 디스크 읽기는 10kb 에서 15MB 로, 지연은 100배로 늘었고 이벤트 수집이 거의 멈췄다.

근본 원인은 문제가 시작되고 하루 반이 지난 11월 12일 22:17 UTC 에야 찾았다. OID 고갈은 큰 규모에서도 드물게 겪는 현상이었다. 표준 대시보드는 이것을 곧바로 가리키지 않았고, TOAST 와 OID 사용량을 보는 관측 수단도 없었다. PostHog 는 AWS RDS 팀 엔지니어와 외부 컨설턴트의 도움을 받았고, 새 파티션 테이블로 옮기는 것 말고는 방법이 없다는 결론에 이르렀다. 새 TOAST 테이블과 OID 공간을 갖는 파티션 Persons 테이블을 만들고, 트리거로 옛 테이블과 새 테이블을 맞추며 기존 데이터를 백필했다. 쓰기는 새 테이블로 보내고 읽기는 새 테이블을 먼저 보고 옛 테이블로 넘어가게 바꿨다. 장애 중 새 문제를 만들지 않으려고 웹 앱은 사람이 통제하는 배포로 내보냈다.

11월 14일 15:02 UTC 에 수집이 정상으로 돌아왔고, PostHog 는 밀린 이벤트 처리에 집중했다. 이때 AWS MSK 에서 따로 문제가 났다. MSK 의 tiered storage 는 최근 4시간치 데이터를 로컬 디스크에 두었다가 S3 로 넘긴다. 밀린 데이터를 따라잡는 동안 이 4시간치가 유난히 커져 로컬 디스크 사용률이 85% 에 닿았다. 수집을 잠시 멈추고 해당 토픽의 로컬 보존 기간을 줄인 뒤, 디스크 여유를 확인하고 수집을 다시 시작했다. 오래 걸릴 백필은 Dagster 로 옮겼다. 11월 15일 06:20 UTC 에 밀린 이벤트를 모두 처리해 완전히 복구했고, 잃은 데이터는 없었다.

심각도
–
영향 범위
Event and persons ingestion for US Cloud, delayed from 10 minutes up to 2 days; analytics on recent data, feature flags and experiments using person properties, filtering in error tracking and session replay, and CDP destinations and workflows were affected
영향 사용자
All customers in the US region
지역
US Cloud
감지까지
–
복구까지
3d 14h 18m

증상

2025년 11월 11일 16:02 UTC 부터 PostHog 수집 처리 파이프라인의 성능이 크게 떨어져, US 리전 모든 고객의 이벤트 처리가 지연되기 시작했다. 고객이 최근에 보낸 이벤트가 PostHog 에 보이지 않았다.

Persons 데이터베이스의 쓰기는 TOAST 테이블에서 쓸 수 있는 OID 를 기다리느라 업데이트 한 건에 몇 초씩 걸렸다. 쓰기 쿼리 하나가 읽는 디스크 양은 10kb 에서 15MB 로 늘었고, 이 쿼리들의 지연은 100배가 됐다. 수집 파이프라인은 보통의 확장 수단으로는 손쓸 수 없을 만큼 느려졌다.

지연은 고객에 따라 10분에서 최대 2일이었다. 최근 기간이 들어간 Analytics 차트와 쿼리는 부정확했고, person 속성을 쓰는 feature flag 는 그 속성이 늦게 반영됐다. Error tracking 과 Session replay 수집은 정상이었지만 Person 업데이트로 거르는 필터는 영향을 받았고, Persons 에 기대는 CDP destination 과 Workflow 는 늦게 실행됐다.

CPU, 메모리, IOPS, 잠금 경합을 보는 표준 대시보드는 OID 고갈을 곧바로 가리키지 않았다. TOAST 테이블 크기나 OID 사용량, 특정 테이블의 쓰기당 디스크 읽기 증폭을 보는 관측 수단이 없어서, 근본 원인을 찾는 데 하루 반이 걸렸다.

11월 14일 수집이 회복된 뒤 밀린 이벤트를 처리하는 동안 AWS MSK 의 로컬 디스크 사용률이 약 85% 까지 올라 알림이 울렸다.

증상 처리량 저하지연 시간 증가

원인

촉발
Persons 테이블의 properties 열은 자주 2KB 를 넘어 TOAST 테이블에 따로 저장되는데, 이 값마다 할당하는 32비트 OID 공간이 거의 다 찼다. 그러자 쓰기 한 건마다 비어 있는 OID 를 찾느라 이미 쓴 OID 를 길게 훑어야 했다.

감지

–

조치

후속 조치

교훈

Persons 테이블 하나에 analytics, feature flag, replay 필터, CDP 같은 핵심 기능 다수가 기대고 있어, 이 테이블이 느려지자 제품의 넓은 부분이 영향을 받았다. TOAST 증가, OID 사용량, 쓰기당 디스크 읽기 증폭을 보는 모니터링이 없어 OID 고갈을 원인으로 확정하는 데 하루 반쯤 걸렸다. 처음의 백필 방식은 길고 큰 마이그레이션에 필요한 가시성과 견고함이 모자라 장애 중에 Dagster 로 옮겨야 했다. MSK 디스크가 차오른 일로 tiered storage 설정과 알림이 큰 백로그 상황에 맞춰져 있지 않았다는 것이 드러났다. 평소 고객 소통을 맡는 팀원이 장애 내내 모두 자리에 없어 대신할 사람을 급히 찾아야 했다.

PostHog 는 잘된 점으로 네 가지를 꼽았다. 데이터를 잃지 않았다. 여러 팀과 외부 컨설턴트, AWS 엔지니어가 함께 드문 엔진 수준 문제를 진단했다. 시스템을 살려 둔 채 트리거와 백필로 새 Persons 테이블로 옮겼다. 엔지니어가 직접 정기적으로 상태를 알렸다.

출처

참고 문서

관련 사례

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 데이터베이스, 메시지 브로커. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.