Files
llm-wiki/raw/company-tech-blogs/kafka-multi-tier-retry-topic-dlq-uber.md

83 lines
11 KiB
Markdown

---
title: company-tech-blog / Uber — Building Reliable Reprocessing and Dead Letter Queues with Apache Kafka
source_type: company-tech-blog
url: https://www.uber.com/en-US/blog/reliable-reprocessing/
archive_url:
related_branches: [feature-kafka-consumer-inbox-contract]
related_projects: [ca-skeleton]
tags: [company-tech-blog, ca-skeleton, messaging, kafka, dead-letter-queue, retry-policy]
created: 2026-07-28
---
# Uber — Building Reliable Reprocessing and Dead Letter Queues with Apache Kafka
> Layer: `raw/` — 외부 자료(대기업 기술 블로그)의 **원문 발췌·출처 기록**.
> 이 자료는 **회사 사례(company-case-study)** 다. 공식 Kafka best practice 로 취급하지 않는다 (CLAUDE.md §5).
## Parent / 활용 branch
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-kafka-consumer-inbox-contract]] | ca-skeleton consumer 의 재시도 전략에서 "다단계 retry topic + DLQ" 대안이 실제 대규모 운영에서 어떤 전제 위에 성립하는지의 사례 근거 — 각 retry 단계가 처리 지연(backoff)을 강제하는 구조, 그리고 이 패턴이 "이벤트를 발생 순서 그대로 처리하지 않아도 되는 애플리케이션"을 전제로 한다는 명시적 인정(= ca-skeleton per-aggregate 순서 보장 계약과 충돌하는 지점) |
## 출처
- 원본 URL: https://www.uber.com/en-US/blog/reliable-reprocessing/
- 아카이브 URL: (미제공)
- 저자 / 조직: Uber Engineering (Insurance Engineering team)
- 발행일: 명시 없음 (WebFetch 결과에 발행 날짜 필드 없음 — `needs-confirmation`)
- 마지막 확인일: 2026-07-28
## 왜 저장했는지
`feature-kafka-consumer-inbox-contract` 브랜치가 검토 중인 "다단계 retry topic + DLQ" 대안의 실제 운영 사례를 확보하기 위해 저장. 특히 이 패턴이 성립하는 전제 — (1) 각 retry topic 단계가 지연(delay)을 강제하는 구조, (2) 파티션 밖에서는 순서를 보장하지 않아도 되는 애플리케이션이어야 한다는 것, (3) at-least-once 전제 하 idempotent consumer 필요 — 를 원문으로 고정한다. (2)는 ca-skeleton 의 per-aggregate FIFO 순서 보장 계약과 정면으로 충돌할 수 있는 지점이라 아래 `## Usage Boundaries`에 명시한다.
## 핵심 인용
> [§Delay Strategy] "Each subsequent level of retry consumers can enforce a processing delay, in other words, a timeout that increases as a message steps down through each retry topic." (line 27)
> [§Important Constraint] "Since Kafka only guarantees in-order processing within partitions and not across them, it must be acceptable for an application to handle events outside of the exact order in which they occur." (line 38)
> [§Important Constraint] "Additionally, consumers must implement idempotent operations due to at-least-once delivery semantics." (line 38, 같은 문단 두 번째 문장)
> [§Solution: Separate Queue Architecture] "Dead Letter Queue → end-of-line for persistent failures" (line 21, 원문 bullet: `**Dead Letter Queue** → end-of-line for persistent failures`)
> [§Solution: Separate Queue Architecture] "When a consumer fails to process a message, it publishes to the retry topic and commits the original offset, allowing batch processing to continue." (line 23)
## Claims Extracted
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| UBER-REPROC-C1 | 다단계 retry topic 구조에서 각 단계는 이전 단계보다 증가하는 처리 지연(timeout)을 강제할 수 있다 (leaky bucket 패턴) | "Each subsequent level of retry consumers can enforce a processing delay, in other words, a timeout that increases as a message steps down through each retry topic." | `company-case-study` | Uber Insurance Engineering 팀의 Kafka 기반 이벤트 재처리 아키텍처 설계 | Kafka 공식 문서가 이 backoff 구조를 권고한다는 것은 증명하지 않는다 (이 인용에는 Kafka 공식 문서 인용이 없음) — 몇 단계가 적정한지, 지연 값을 어떻게 산정하는지는 이 문서 범위 밖 |
| UBER-REPROC-C2 | Kafka 는 파티션 내부(within partitions)에서만 순서를 보장하고 파티션을 가로질러(across them)는 보장하지 않으므로, 이 재처리 아키텍처를 채택하려면 애플리케이션이 이벤트를 발생 순서 그대로 처리하지 않아도 되는 것을 받아들여야 한다 | "Since Kafka only guarantees in-order processing within partitions and not across them, it must be acceptable for an application to handle events outside of the exact order in which they occur." | `company-case-study` | retry topic + DLQ 로 메시지가 원본 topic → retry topic(들) → DLQ 로 이동하는 구조 전반 | **ca-skeleton 의 per-aggregate FIFO 순서 보장 계약이 이 패턴과 양립 가능한지는 증명하지 않는다** — 오히려 이 전제(순서 비보장 수용)가 ca-skeleton 계약과 정면으로 다를 수 있다는 것이 이 인용의 핵심 사용처. 이 페이지는 Kafka 공식 문서를 인용하지 않으므로 "파티션 내부만 순서 보장"이라는 Kafka 자체의 공식 동작도 이 문서만으로는 `official-standard`/`official-vendor-doc` 급으로 격상되지 않는다 (별도 공식 문서 보강 필요) |
| UBER-REPROC-C3 | 이 아키텍처에서는 at-least-once 전달 시맨틱을 전제하므로 consumer 가 idempotent 연산을 구현해야 한다 | "Additionally, consumers must implement idempotent operations due to at-least-once delivery semantics." | `company-case-study` | Uber 의 retry/DLQ consumer 설계 전제 | idempotency 를 **어떻게** 구현해야 하는지(메커니즘)는 말하지 않는다 — ca-skeleton 의 owner-token 기반 idempotency 프로토콜 (`feature-idempotency-ownership-protocol-contract` 소유) 과의 구체적 정합성은 이 인용만으로 증명되지 않는다 |
| UBER-REPROC-C4 | consumer 가 메시지 처리에 실패하면 retry topic 으로 publish 하고 원본 offset 을 즉시 commit 하여, 이후 배치 처리가 막히지 않고 계속 진행된다 | "When a consumer fails to process a message, it publishes to the retry topic and commits the original offset, allowing batch processing to continue." | `company-case-study` | Uber 의 실패 메시지 처리 흐름(원본 topic에서의 offset 커밋 시점) | ca-skeleton 의 manual-ack·bounded-concurrency 설계에서 동일한 "실패 시 즉시 원본 offset commit" 방식을 채택해야 한다는 것은 증명하지 않는다 — 이는 Uber 의 설계 선택이며 대안(예: 원본 offset 을 보류하고 재시도)과의 트레이드오프 비교는 이 문서에 없다 |
| UBER-REPROC-C5 | Dead Letter Queue 는 재시도 단계를 모두 소진한 지속적 실패 메시지의 최종 종착점(end-of-line)이다 | "Dead Letter Queue → end-of-line for persistent failures" | `company-case-study` | Uber 아키텍처에서 DLQ 의 역할 정의 | DLQ 재처리(replay) 절차·모니터링·알림 방식의 구체 사항은 이 인용 범위 밖 — ca-skeleton 의 "감사된 replay" 요구사항과의 구체적 정합성은 별도 확인 필요 |
## Usage Boundaries
- 이 자료가 직접 증명하는 것:
- `UBER-REPROC-C1`: 다단계 retry topic 각 단계가 증가하는 지연을 강제할 수 있다는 Uber 의 설계 서술
- `UBER-REPROC-C2`: Uber 가 이 패턴을 채택하려면 "이벤트를 발생 순서대로 처리하지 않아도 되는 것"을 전제로 명시적으로 인정했다는 것
- `UBER-REPROC-C3`: at-least-once 전제 하 idempotent consumer 필요성에 대한 Uber 의 서술
- `UBER-REPROC-C4`: 실패 시 retry topic publish + 원본 offset commit 이라는 Uber 의 구체적 메커니즘
- `UBER-REPROC-C5`: DLQ 를 지속 실패 메시지의 최종 종착점으로 규정한다는 것
- 이 자료가 증명하지 **않는** 것 (중요 — ca-skeleton 적용 전 반드시 확인):
- **이 패턴이 "공식 Kafka best practice"라는 것.** 이 문서는 `company-case-study` 등급이며, Kafka 공식 문서(vendor-doc)의 보강 인용이 이 노트 안에 없다. `UBER-REPROC-C1`/`C2` 를 "Kafka 가 권장하는 방식"으로 서술하면 CLAUDE.md §5·§11 위반(공식 문서와 기술 블로그 혼동)이다.
- **ca-skeleton 의 per-aggregate FIFO 순서 보장 계약과의 양립 가능성.** `UBER-REPROC-C2` 는 오히려 이 패턴이 "순서 비보장을 받아들이는 애플리케이션"을 전제로 함을 명시한다 — ca-skeleton 이 per-aggregate 순서를 보장해야 하는 도메인이라면, retry topic 으로 메시지를 우회시키는 순간 해당 aggregate 의 이후 이벤트가 원본 partition 순서를 앞지를 수 있다는 위험을 이 인용이 시사한다. 이 노트는 그 위험을 **제기**할 뿐, ca-skeleton 에서 실제로 문제가 되는지/어떻게 완화하는지는 증명하지 않는다.
- idempotency 구현 메커니즘의 구체 사항 (owner token protocol 등) — `feature-idempotency-ownership-protocol-contract` 브랜치 소관.
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-skeleton 이 실제로 per-aggregate FIFO 순서를 어느 범위까지 보장하기로 결정했는지 (`feature-kafka-consumer-inbox-contract` §결정-근거 매핑에서 확정 필요) — 이 근거와 대조해야 "다단계 retry topic" 채택 여부를 판단할 수 있다
- Kafka 자체의 "파티션 내부만 순서 보장" 공식 진술 보강 — 현재 vault 의 `raw/official-docs/kafka-message-delivery-semantics-design.md` 는 delivery semantics(at-least-once/exactly-once)만 다루고 ordering-within-partition 자체는 다루지 않는다. 별도 official-doc 수집 필요.
## 메모
- 이 노트의 인용 5개 전부 Self-Grep 통과 (아래 리포트 참조). fabrication 없음.
- Uber 블로그는 "leaky bucket pattern" 이라는 표현도 쓰지만 (본문: "This follows a leaky bucket pattern, preventing request spam.") 이는 별도 인용으로 뽑지 않았다 — Uber 의 해설(패턴 이름 붙이기)이지 구체적 수치·메커니즘 진술이 아니라서 5개 핵심 인용에서는 제외. 필요 시 추가 가능.
- 발행일이 WebFetch 결과에 없어 `needs-confirmation` 으로 남긴다. 원문 페이지에 날짜 메타데이터가 있는지는 브라우저 렌더링으로 재확인 필요할 수 있음.
## 관련
- 같은 도메인 인접 official-doc: [[raw/official-docs/kafka-message-delivery-semantics-design.md]] — at-least-once/idempotent producer 정의 (이 문서가 언급하는 "idempotent consumer 필요성"의 배경이 되는 delivery semantics)
- 이 자료를 인용한 wiki 요약: (생성 시 링크)