05.07.2026 • 5 min read

DesignFlix 21: What a Dead Letter Queue Does After Retries Fail

What should a worker do with a message that keeps failing?

Retrying sounds reasonable until the same message fails for the fiftieth time. Meanwhile, valid jobs are waiting, the error logs are growing, and nobody is any closer to fixing the cause.

A dead letter queue gives those failures a place to wait for investigation. Let's follow one delivery job through retries, isolation and recovery, because moving a message out of the main queue is only half the work.

First, ask why the job failed

Suppose an online shop queues a job to create a delivery label. The worker reads the order, calls a courier API, saves the label and acknowledges the message.

Two failures can happen at the same step. The courier may be temporarily unavailable, or the job may contain an address with a required field missing. A later attempt could solve the first; repeatedly sending the same incomplete address won't solve the second.

That distinction should shape the retry policy. Check the error instead of assuming every failure needs another immediate attempt. Invalid input can go straight to a failure path, while a temporary outage may deserve a few delayed retries.

Give retries time and a limit

A retry needs enough time for the cause to change. Hammering an unavailable courier ten times in one second mainly adds traffic to an already struggling service.

Use a bounded policy with increasing delays, and consider adding randomness so many workers don't retry together. An illustrative schedule might wait 5 seconds, then 20, then 60. Those numbers aren't a universal setting; choose them around the operation's deadline and the downstream service.

Also decide what an attempt means in your queue. For example, Amazon SQS uses a receive-count threshold in its redrive policy. Don't assume that count is a perfect record of completed business attempts.

Give the failure somewhere to wait

When the permitted attempts are exhausted, the system can route the message to a dead letter queue, usually shortened to DLQ. We keep the failed job available for investigation instead of letting it consume the same processing capacity indefinitely.

The original flow from message processing and retries to a dead letter queue

Healthy messages can then continue according to the queue's delivery rules. If your workload depends on strict ordering, check what removing a failed message does to that ordering. An order-update stream may need a different recovery plan from independent delivery-label jobs.

The routing mechanism depends on the product. RabbitMQ's dead-letter exchanges support several causes of dead-lettering. In Kafka applications, a dead-letter topic is commonly an application or connector convention. These aren't interchangeable configuration switches.

The Terminator scene

I'll be back. After the fix.

The Terminator · Tenor · Adapted dialogue

Save enough context to investigate

A failed payload by itself can leave us guessing. We need to find the original job, understand what happened, and decide whether replay is safe.

Useful context includes:

  • A stable message ID and the business operation it belongs to.
  • The original payload and its schema version.
  • The latest error, with earlier attempts traceable in logs.
  • Attempt times, failure time and the worker or handler version.
  • A request or trace ID linking the job to the original request.

Store only the sensitive data the investigation actually requires, and restrict access to it. A queue full of failed delivery addresses still contains delivery addresses.

For our example, the record might say missing_pincode, point to order 318, and identify the payload version. That is enough to begin a useful investigation. "Job failed" isn't.

A quiet main queue can hide unfinished work

Once the failure moves aside, the main queue may look healthy. The customer still has no delivery label.

If the main queue is empty but the DLQ keeps growing, have we finished the work or just moved it?

Track the number of failed jobs and the age of the oldest one. Alert the people who can act on those signals, and make the customer-facing state honest: label creation failed or needs attention, rather than complete.

A DLQ is useful because it preserves a problem we can repair. Without an owner and a recovery process, it becomes a quieter way to forget the problem.

Fix the cause before replaying the message

Suppose the address is corrected. We now have a reason to retry the job, but we should check whether the courier already created a label during an earlier attempt.

A timeout can hide a successful external action. If we blindly replay, the courier might create a second label. Use a stable operation ID, the courier's idempotency support where available, or a reconciliation lookup appropriate to its API.

Replay a small batch first, watch the results, and avoid flooding a service that has just recovered. Keep a record of what was replayed and why. If a message needs repair, preserve the original failure details rather than erasing the evidence.

Design the way back in

A DLQ helps the queue keep moving while giving failed work a recoverable state. It doesn't fix the payload, complete the job or create a missing delivery label.

Before shipping a queue-based feature, test one job that fails permanently and one that succeeds but loses its response. Then practise finding, fixing and replaying them. If you can explain what happens to both, the DLQ is doing more than making the dashboard look clean.

Try it yourself

A delivery-label job times out, reaches the DLQ after retries, and is later replayed. Why could this create duplicate labels, even though every recorded attempt failed?

A possible solution

A recorded timeout means the worker did not obtain a successful response; it does not prove that the courier failed to create the label. Reconcile the earlier operation using its stable identifier or use supported idempotency before replaying. Preserve the failure record, then retry under a policy that makes duplicate delivery of the same job safe.

Share this article with your friends

Know someone who would enjoy this? Send it their way.

WhatsAppLinkedInXEmail