Skip to content
기능요금제제휴블로그도움말회사 소개문의하기
무료로 시작하기로그인
블로그로 돌아가기
guides2026-08-295 분 읽기

Webhook 멱등성: Stripe가 동일한 커미션 이벤트를 세 번 발사할 때

Stripe의 at-least-once 전달은 프로덕션에서 약 0.3%의 중복 이벤트를 의미합니다. thMenu의 stripe_webhook_events claim 패턴이 중복을 처리하는 방법 — 레이스 컨디션 수정 포함.

th

thMenu Team

thmenu.com

14개월 동안 thMenu의 모든 Stripe webhook을 기록했습니다: 100,000개 이벤트 중 312개가 동일한 event_id로 두 번 또는 세 번 도착했습니다. Stripe의 "at-least-once delivery" 약속을 구체적인 숫자로 — 멱등성 없이는 커미션 원장에 세 개의 중복 행.

동일 이벤트가 세 번 도착하는 이유

Stripe가 약 10초 내에 2xx 응답을 받지 못하면 재시도합니다. TCP 타임아웃, lambda 콜드 스타트, 일시적 DNS 장애, 성공적 처리 후 응답 쓰기 전 연결 끊김 — 모두 재시도를 트리거합니다.

세 가지 빈번한 시나리오: Cloudflare Workers 콜드 스타트 10초 초과, D1 batch 트랜잭션 커밋됐지만 연결 끊김, Stripe 대시보드에서 수동 "resend" 클릭.

INSERT-Claim 패턴

thMenu의 방어는 stripe_webhook_events 테이블에 event_id PRIMARY KEY. 첫 동작: INSERT. Unique 제약 오류 23505 = 중복 — 200 OK no-op.

중요: claim은 비즈니스 로직보다 먼저 와야 합니다. 그렇지 않으면 레이스 컨디션.

레이스 컨디션: 순서 어긋난 이벤트

실제 프로덕션 사건: customer.subscription.updatedcheckout.session.completed보다 800ms 먼저 도착. UPDATE 0행 영향. 수정: claim 롤백, 503 반환, Stripe 재시도.

FAQ

서명 검증은 claim 전후 어느 쪽? 전. Verify는 저렴, DB 쓰기는 비쌈.

멱등 테이블 보관 기간? Stripe는 30일 재시도 보장; 우리는 90일 보관.

Stripe가 영원히 재시도? 아니요, 최대 3일.

도움이 되셨나요? 공유해 주세요.