When Event Time Meets Reality: Lessons from Building Billing on Apache Flink (Gorgias)

Author: Matthieu Bonneviot (Gorgias) | Source: Medium (Gorgias Engineering) | Published: 2026-06-03


한 줄 요약

Gorgias가 Flink 72시간 consolidation window billing을 event-time으로 구축하며, watermark alignment가 source 레벨에만 적용되어 keyBy 재파티셔닝 후 event-time 순서가 깨지는 한계를 발견하고 우회책으로 해결.

핵심 주장/내용

  • billing은 event-time 필수: processing-time이면 지연 이벤트가 잘못된 window에 집계(history 리플레이가 수일치를 한 window로 collapse). event-time + watermark로 해결
  • 현실의 Kafka: 단일 ordered queue 가정이 깨짐(토픽=다수 파티션, 순서는 파티션 내만 보장). Flink는 global watermark = 모든 병렬 watermark의 minimum. watermark alignment 필수(스트림이 너무 앞서가지 않게)
  • out-of-order 처리: crash 후 checkpoint/offset 재시작 → 중복·오래된 event time 재유입. bounded out-of-orderness watermark로 “얼마나 늦어도 되는가” 정의
  • watermark idleness: 저트래픽 source나 파티션보다 많은 subtask가 watermark 진행을 막음 → idle 표시로 제외
  • 핵심 한계 발견: 두 번의 keyBy(dedup → consolidation) 후 재파티셔닝으로 event time 순서 붕괴 → overlapping window. watermark alignment는 source 레벨만 → 재파티셔닝 후 정렬 미보존
  • 우회책: ① event-time operator 앞은 동일 key 사용(중복 keyBy 회피, overlap ~10x 감소) ② historical replay 시(event ts가 system time보다 한참 오래됨) consolidation을 +1일 지연(실시간은 무영향) ③ window emit 후 stale timer 명시적 삭제

주요 수치 / 사실

  • 72시간 consolidation window, Kafka → Flink
  • dedup/consolidation을 같은 key(customer/user)로 통일 → overlap ~10x 감소
  • replay 감지: event ts vs Instant.now() lag > 15분이면 reprocessing으로 간주
  • 교훈: “watermark를 올바로 설정하는 건 해법의 일부일 뿐 — stateful operator·재파티셔닝·history 리플레이가 얽히면 실행 그래프 전체의 event time 전파 이해가 필수”

관련 위키


Source: 원문 보기