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: 원문 보기