idempotency ledger

중복 요청은 키 저장소의 상태 전이로 판별한다

결제, 주문, 메시지 소비처럼 재시도가 자연스러운 작업은 요청 키를 유니크하게 저장하고, 처리 중인 요청과 이미 완료된 요청을 서로 다른 응답으로 다뤄야 합니다.

요청 도착

키와 해시 확인

같은 키라도 payload hash가 다르면 재시도가 아니라 충돌 요청으로 거절합니다.

원자 삽입

in_progress 생성

idempotency row와 업무 변경을 가능한 한 같은 트랜잭션에서 시작합니다.

중복 처리

진행 중 응답

첫 요청이 아직 커밋 전이면 409 또는 202로 기다리게 하고, 같은 작업을 다시 실행하지 않습니다.

완료 저장

completed 전이

업무 커밋 뒤 결과 snapshot을 저장해 브라우저 재시도와 네트워크 재전송을 흡수합니다.

실패 만료

failed 또는 ttl

부분 실패는 재시도 가능 상태와 만료 시간을 분리해 운영자가 복구할 수 있게 남깁니다.

동시성

락은 짧게, 제약은 단단하게

  • 키 row 삽입은 unique violation을 정상 분기로 다룹니다.
  • 긴 외부 API 호출은 상태를 남기고 timeout 정책을 둡니다.
재응답

완료 후에는 저장 결과를 반환

사용자가 새로고침해도 주문 번호와 결제 결과가 바뀌지 않도록 이전 응답을 그대로 재생합니다.

정리

TTL은 감사 기간과 맞춘다

너무 짧은 TTL은 느린 재시도를 새 요청으로 만들고, 너무 긴 TTL은 키 저장소를 불필요하게 키웁니다.