---
url: https://docs.nemo12.com/ops/dlq-replay.md
description: >-
  Cách xem và chạy lại message chết của queue nemo12-events: bảng D1
  queue_dead_letters là nguồn sự thật sau 5 lần retry.
---

# Message chết (dead letter)

Queue `nemo12-events` retry tối đa 5 lần với backoff (`workers/api/wrangler.jsonc`, consumer trong
`workers/api/src/index.ts`). Hết lượt thì consumer ghi message vào bảng D1 `queue_dead_letters` rồi mới
ack, nên **sổ D1 là nguồn sự thật**, không phải queue `nemo12-events-dlq` của Cloudflare (được khai
nhưng không có consumer — cố ý, xem [queues](../reference/queues.md)).

## Xem

* Admin → Ops (admin.nemo12.com, sau Cloudflare Access), hoặc `GET /v1/admin/dead-letters` (vai admin).
* Mỗi dòng (`queue_dead_letters`, migration 0036): `message_id`, loại event, `error_text` (lỗi lần cuối),
  và `replay_status` (`pending` · `replayed` · `failed` · `discarded`).

## Chạy lại

`POST /v1/admin/dead-letters/{id}/replay` (nút trên Admin → Ops). An toàn để bấm nhiều lần: consumer
claim theo khoá `type:idempotency_key` trong KV trước khi xử lý và chỉ mark sau khi thành công
(`shared/reliability.ts`), nên message đã xử lý xong sẽ bị bỏ qua. Mỗi lần replay để lại một dòng
`audit_log` với action `dlq.<replay_status>` (`dlq.replayed` hoặc `dlq.failed`).

## Khi nào KHÔNG replay

* Lỗi là do payload sai hình (schema đổi): replay lại vẫn chết. Sửa consumer trước.
* Handler của `type` đó vẫn là no-op (hiện tại 22 event chưa có consumer nghiệp vụ — Audit #013
  C-18): replay chỉ đổi trạng thái sổ, không tạo ra kết quả gì.

## Cảnh báo

Chưa có alert tự động khi bảng này tăng (Audit #013 I-9, việc tay: Cloudflare Notifications + uptime).
Tới lúc đó: mở Admin → Ops mỗi sáng, hoặc đếm `queue_dead_letters` có `replay_status='pending'` qua
`GET /v1/admin/dead-letters`.
