Files
tech-log-backend/docs/runbooks/job-dead-letter.md
T

3.3 KiB

title, category, error_codes, severity, owner, last_updated, status
title category error_codes severity owner last_updated status
Runbook — background job dead letter INTERNAL
JOB_DEAD_LETTER
P1 oncall 2026-06-13 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 원인 분류 기록, 같은 원인의 재발 방지 테스트 추가

Stub 상태 안내: 이 runbook은 skeleton 단계의 stub. retry carrier(Spring Retry / Resilience4j / 자체) 확정 후 DLQ 저장소·재처리 절차 보강 필요.