--- title: Runbook — background job dead letter category: INTERNAL error_codes: [JOB_DEAD_LETTER] severity: P1 owner: oncall last_updated: 2026-06-13 status: stub --- # Runbook: background job dead letter (`runbook://job/dead-letter`) ## 1. Trigger 이 runbook은 다음 alert에서 발동됩니다. - alert name: `job_dead_letter` - alert payload 필수 field: `error.code=JOB_DEAD_LETTER`, `job_name`, `correlation_id`, `runbook_link` - 임계: `job.dlq.total` > 0 for 5m (p1) — retry 소진 후 DLQ 진입은 자동 회복이 없으므로 점검 대상 ## 2. First Response (5분 이내) ### Step 1 — 확인 1. ERROR log에서 `JOB_DEAD_LETTER` 라인 확인: `job_name`, 최종 실패 원인 예외, `correlation_id` 추출 2. `job.retry.total{outcome=EXHAUSTED}` 추이로 DLQ 유입 규모 파악 3. DLQ 적재 위치(향후 retry carrier 확정 시 DB 테이블/큐) 확인 — 현재 skeleton은 vocabulary 단계 ### Step 2 — 임시 격리 - DLQ는 max attempts(3) 소진의 최종 상태 — 자동 재시도 없음, 수동 개입 필수 - 비즈니스 크리티컬 job이면 §4의 수동 처분(재처리 또는 폐기)을 우선 수행 ## 3. Diagnosis - log query: `{service="app"} | error.code="JOB_DEAD_LETTER" | stats count by job_name` - metric panel: `job.dlq.total{job_name}`, `job.retry.total{job_name, outcome}` - 최종 실패 원인 분류: - poison input(직렬화/계약 위반) → 입력 결함, 재처리해도 실패 — 수정 후 재처리 또는 폐기 - 외부 의존성 장기 outage 중 attempts 소진 → 의존성 회복 후 재처리로 해결 가능 - non-transient error(권한/도메인/스키마)인데 retry된 경우 → 분류기 보강 필요(WAF-REL05-C3: 즉시 DLQ가 정답) ## 4. Mitigation (수동 처분 — 둘 중 하나) - **재처리 (기본)**: 원인 해소 후 해당 job을 다시 enqueue. 소비자는 멱등(idempotencyKey dedupe) 의무가 있으므로 중복 처리 안전 - **폐기 (영구)**: 작업이 더 이상 유효하지 않으면 DLQ에서 제거. ⚠ 비즈니스 오너 승인 후에만 수행하고 incident 기록에 남김 - 장기: poison input 재발 방지(입력 계약 테스트 보강), non-transient error는 retry 없이 즉시 DLQ로 분류 ## 5. Escalation - 처분 판단(재처리 vs 폐기)이 불가하면 해당 job의 비즈니스 오너에게 escalate - DLQ 누적이 특정 `job_name`에 집중되면 해당 job 코드 오너에게 page ## 6. Recovery / Verification - 회복 확인: `job.dlq.total` 증가 멈춤, 재처리분의 소비자 dedupe 동작 확인 - post-incident: DLQ 원인 분류 기록, 같은 원인의 재발 방지 테스트 추가 ## 7. Related - error-codes.yaml rows: `JOB_DEAD_LETTER` (INTERNAL, 500, retryable=false) - metrics.yaml: `job.dlq.total{job_name}`, `job.retry.total{job_name, outcome=DLQ}` - 코드: `app-bootstrap` `async/BackgroundJobMetrics`(retry/DLQ vocabulary 기록 seam — D2/D4) - 관련 runbook: [[job-executor-rejected]], [[job-timeout]], [[outbox-dead-letter]] - 관련 branch: [[feature-background-job-async-contract]] (D4 retry/DLQ vocabulary SSOT — outbox/outbound가 consume) --- > **Stub 상태 안내**: 이 runbook은 skeleton 단계의 stub. retry carrier(Spring Retry / Resilience4j / 자체) 확정 후 DLQ 저장소·재처리 절차 보강 필요.