-
[Cloudflare Queues][운영] DLQ replay를 끝낸 뒤 duplicate check 결과와 idempotency 메모를 어떤 closure row로 같이 남기나기타개발지식/풀스택개발 2026. 9. 1. 09:13
IT 리서치 노트
[Cloudflare Queues][운영] DLQ replay를 끝낸 뒤 duplicate check 결과와 idempotency 메모를 어떤 closure row로 같이 남기나
Cloudflare Queues에서 DLQ replay를 끝냈는데도 incident note가 길어지는 이유는 대개 종료 근거가 분산돼 있기 때문이다. 2026년 9월 1일 KST 기준 Cloudflare 공식 문서를 다시 보면 pull API는 message와 backlog 필드를 함께 주고, dashboard preview는 acknowledge나 retry를 일으키지 않으며, DLQ는 최대 재시도 횟수를 넘긴 메시지의 격리 경로다. 이 글은 DLQ replay를 끝낸 뒤 duplicate check 결과와 idempotency 메모를 어떤 closure row로 같이 남겨야 하는지 정리한다.
1. 개요
결론부터 말하면 DLQ replay closure는
replay 성공한 줄이 아니라duplicate check 결과와idempotency 메모를 함께 남겨야 한다. replay만 끝났다고 incident를 닫으면 downstream side effect 중복이나 tail 잔존을 놓치기 쉽다.특히 preview fetch는 queue 상태를 바꾸지 않으므로 replay 직후 closure 판단은 preview 확인 시각, message id, idempotency key hit 여부를 같은 row에 두는 편이 안전하다. post 445와 post 442가 이미 owner와 dump 근거를 정리했다면, 이번 단계는 incident를 닫아도 되는지의 기준을 채우는 일이다.
2. 어디서 실제로 막히는가
실무에서 먼저 꼬이는 지점은 세 가지다. 첫째, replay가 성공했다는 응답만 보고 duplicate check를 생략한다. 둘째, duplicate 여부는 downstream 로그에서 보고 idempotency 메모는 queue ticket에 따로 적는다. 셋째, preview 재확인 시각이 없어 close가 replay 직후였는지, 나중에 side effect를 본 뒤였는지 구분이 안 된다.
Cloudflare 문서는 pull API 응답에 attempts, lease_id, backlog 필드를 함께 노출하고, dashboard preview는 acknowledge나 retry를 발생시키지 않는다고 설명한다. 즉 replay 이후 closure note는 body 캡처보다 delivery 맥락과 상태 확인 시각을 같이 남겨야 한다.
또 DLQ는 최대 재시도 횟수를 넘긴 메시지의 격리 경로다. 이 말은 replay가 끝났어도 같은 message id의 side effect가 이미 외부 시스템에 반영됐는지 따로 확인해야 한다는 뜻이다. replay 성공과 incident 종료는 같은 사건이지만 같은 순간이 아닐 수 있다.
- 증상: replay는 끝났는데 incident close 근거가 약하다.
- 실패: duplicate check 결과와 idempotency 메모를 다른 도구에 나눠 쓴다.
- 막힘: preview 확인 시각이 없어 closure 시점을 설명하지 못한다.
- 누락: downstream side effect 중복 여부를 안 적는다.
겉으로 보이는 현상 같이 남겨야 할 값 판단 기준 replay 성공 후 close 여부가 모호하다 preview 재확인 시각, duplicate check 상태를 바꾸지 않는 읽기 경로로 다시 봤는지 확인한다 같은 side effect가 다시 났는지 모른다 idempotency key, downstream 결과 재처리와 중복 반영을 분리한다 incident close 시점이 모호하다 closure_state, next_action replay 완료와 close 완료를 나눈다 3. 실무에서 적용하는 순서
가장 짧은 운영 순서는 다섯 단계다. 먼저 replay 직전 dump와 message id를 고정한다. 다음으로 replay 직후 preview 경로로 queue 상태를 다시 본다. 세 번째로 같은 message id의 downstream side effect와 idempotency key hit 여부를 적는다. 네 번째로 duplicate가 없을 때만 closure_state를 닫는다. 마지막으로 duplicate가 있거나 preview가 애매하면 close 대신 수동 검토 상태를 남긴다.
- replay 직전과 직후의 근거 파일을 구분해 저장한다.
- preview 시각과 확인자를 closure row에 적는다.
- duplicate check 결과를 downstream 로그와 함께 적는다.
- idempotency key hit 여부를 별도 칸으로 남긴다.
- close와 manual-review를 명시적 상태로 분리한다.
이렇게 하면 incident 종료가 짧아진다. queue 쪽에서 replay는 끝났지만 비즈니스 시스템에서는 같은 order나 sync가 두 번 반영됐을 수 있기 때문이다. close라는 말을 쓰기 전에 duplicate check와 idempotency 메모가 채워졌는지 먼저 보는 편이 안전하다.
post_replay_preview=done duplicate_check=required idempotency_key_checked=true downstream_side_effect=no-duplicate-write closure_state=closed-after-review4. 공식 문서와 예시 화면으로 확인하기
첫 자료는 Cloudflare Queues metrics 문서다. 여기서는 realtime backlog가 point-in-time 값이며 backlog_count와 oldest_message_timestamp_ms를 바로 읽을 수 있다고 설명한다.
즉 replay closure를 남길 때는 성공 여부 한 줄만 적으면 부족하다. replay 뒤 backlog tail이 실제로 줄었는지까지 한 row에서 다시 읽을 수 있어야 한다.
두 번째 자료는 dashboard preview 문서다. 이 경로는 preview fetch가 acknowledge나 retry를 일으키지 않는다고 설명한다.
그래서 replay 직후 확인 자료는 실제 재처리를 다시 일으키는 live fetch보다 preview 기준 dump와 확인 시각을 먼저 남기는 편이 좋다.
세 번째 자료는 dead letter queue 문서다. Cloudflare는 최대 재시도 횟수를 넘긴 메시지가 DLQ로 간다고 설명한다.
이 전제를 놓치면 replay를 한 번 마쳤다는 이유만으로 incident를 닫게 된다. 실제로는 duplicate check가 남았거나, 같은 message id가 다른 side effect를 다시 일으킬 수 있다.
실무에서는 replay owner와 failed dump는 남겼는데, duplicate check 결과와 closure 판단이 다른 도구에 흩어지는 경우가 많다. 아래 표는 replay 후 closure row를 어떻게 닫을지 정리한 예시다.
이미 failed message dump와 reviewer 메모 글을 봤다면, 이번 글은 그 다음 단계인 종료 근거 정리다. 또 failed position과 replay owner 글과도 같은 incident 사다리로 이어진다.
마지막 자료는 closure note JSON 예시다. 핵심은 replay 성공 여부가 아니라 duplicate 확인 근거와 idempotency 판단을 같이 남기는 것이다.
이 정도 구조면 post 436의 tail incident, post 439의 disposition, post 445의 reviewer 메모가 하나의 closure 흐름으로 이어진다. approval timestamp와 replay result를 같은 종료 row에 붙이는 후속 정리는 replay owner와 reviewer 분리 글에서 바로 이어서 볼 수 있다.
5. 주의사항과 리스크
첫 번째 리스크는 replay 응답만 보고 incident를 닫는 것이다. 두 번째 리스크는 duplicate check 결과를 사람이 읽는 코멘트로만 남겨 다음 incident에서 자동 비교가 안 되는 것이다. 세 번째 리스크는 preview 확인 없이 live fetch만 반복해 queue 상태를 다시 흔드는 것이다.
운영 전에는 최소한 message id, attempts, preview 확인 시각, duplicate check 결과, idempotency key, closure_state 여섯 칸을 같은 row로 두는 편이 좋다. 그래야 replay 성공과 incident 종료를 다른 단계로 관리할 수 있다.
- replay 완료와 incident close를 같은 의미로 쓰지 않는다.
- duplicate check는 자유문장보다 구조화된 칸으로 남긴다.
- queue를 다시 흔들지 않는 preview 경로를 closure 확인에 우선한다.
6. 결론
Cloudflare Queues에서 DLQ replay를 끝냈다는 사실만으로 incident를 닫으면 근거가 약하다. replay 뒤 duplicate check 결과와 idempotency 메모를 같은 closure row에 붙여야 비로소 종료 판단이 짧고 단단해진다.
- preview 재확인과 downstream 확인을 둘 다 남긴다.
- idempotency 메모를 closure row에 함께 둔다.
- close와 manual-review를 다른 상태로 적는다.
7. 참고 링크
'기타개발지식 > 풀스택개발' 카테고리의 다른 글