Lessons from Using the Outbox Pattern at Scale
Author: Sugat Mahanti | Source: https://zapier.com/blog/lessons-from-using-outbox-pattern-at-scale/ | Published: 2026-03-30
한 줄 요약
Zapier는 Kafka 장애 시에도 이벤트를 계속 수신하기 위해 SQLite 기반 Transactional Outbox 패턴을 도입하고, WAL 모드 전환과 50개 샤드 분할로 초당 15,000 이벤트를 처리했으나, StatefulSet/EBS 의존성 등의 한계로 S3+SQS 기반 사이드카 방식으로 전환하고 있다.
핵심 주장/내용
- Kafka 프로듀서 레이턴시 스파이크와 클러스터 장애 시 이벤트 손실을 방지하기 위해, 로컬 SQLite를 outbox로 사용하여 이벤트를 먼저 저장하고 이후 Kafka로 발행하는 방식을 채택했다
- 초기 SQLITE_BUSY 에러를 해결하기 위해 WAL 모드 전환, 50개 파일로의 SQLite 샤딩, 샤드별 mutex 적용, auto_vacuum=FULL 등의 최적화를 순차적으로 적용했다
- SQLite DB는 Kubernetes StatefulSet의 EBS 볼륨에 저장하여 Pod 크래시에서도 데이터를 보존했으나, StatefulSet의 느린 배포/AZ 제약/스케일링 한계가 운영 부담이 되었다
- Kafka 발행 전 outbox 삭제를 위해 동기식 프로듀서 호출이 필요했고, 대규모 백로그 발생 시 VACUUM으로 인한 느린 복구가 문제였다
- 현재는 S3+SQS 기반 폴백 인프라가 충분히 성숙하여, 로컬 SQLite outbox를 hot path에서 제거하고 사이드카 모드로 전환 중이다
주요 수치 / 사실
- 피크 처리량: 약 15,000 events/sec
- SQLite 샤드 수: Pod당 50개 파일
- 전달 보장: at-least-once delivery
- 사용 기술 스택: Go, Kubernetes StatefulSet, EBS 볼륨, SQLite WAL 모드, Kafka (Avro + Schema Registry)
- 신규 아키텍처: 실패 이벤트를 S3에 기록하고 SQS 메시지로 참조하여 나중에 재처리
관련 위키
Source: 원문 보기