Skip to main content

Implementing Dead Letter Queues

1. Understanding DLQ Pattern

Aspect Description Detail
DLQ Topic for failed messages Quarantine
Goal Don't block pipeline Isolate poison
Recovery Inspect, fix, replay Manual/auto

Example: DLQ flow

orders -> process (fail) -> orders.dlq (with error metadata)

2. Creating DLQ Topic

Aspect Description Detail
Naming <topic>.dlq convention Clear
Retention Longer than source Time to fix
Partitions Match or fewer Sufficient

Example: Create DLQ

kafka-topics.sh --bootstrap-server localhost:9092 --create \
  --topic orders.dlq --partitions 3 --replication-factor 3 \
  --config retention.ms=1209600000

3. Routing Failed Messages

Aspect Description Detail
Try/Catch Catch processing error Per record
Forward Produce to DLQ Original payload
Commit Advance source offset After DLQ ack

Example: Route to DLQ

try { process(r); }
catch (Exception e) {
  dlq.send(new ProducerRecord<>("orders.dlq", r.key(), r.value()));
}

4. Configuring DLQ in Streams

Aspect Description Detail
Deser Handler Send bad records to DLQ Custom
Branch Route invalid downstream split()
Production Handler Handle output errors Custom

Example: Branch invalid records

stream.split()
  .branch((k,v) -> isValid(v), Branched.withConsumer(s -> s.to("orders.clean")))
  .defaultBranch(Branched.withConsumer(s -> s.to("orders.dlq")));

5. Using DLQ in Connect

Config Description Detail
errors.tolerance all = route bad Don't fail
errors.deadletterqueue.
topic.name
DLQ topic Sink only
context.headers Add error metadata enable

Example: Connect DLQ config

{"errors.tolerance":"all",
 "errors.deadletterqueue.topic.name":"orders.dlq",
 "errors.deadletterqueue.context.headers.enable":"true"}

6. Adding Error Metadata

Header Description Detail
error.message Exception text Diagnose
error.class Exception type Categorize
source.offset Original location Trace

Example: Add error headers

ProducerRecord<String,String> d = new ProducerRecord<>("orders.dlq", r.key(), r.value());
d.headers().add("error.message", e.getMessage().getBytes());
d.headers().add("error.class", e.getClass().getName().getBytes());
dlq.send(d);

7. Monitoring DLQ

Metric Description Detail
DLQ Rate Messages/sec to DLQ Health signal
DLQ Size Backlog count Lag
Alert Threshold breach Page

Example: Watch DLQ lag

kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --describe --group dlq-monitor

8. Reprocessing DLQ Messages

Step Description Detail
Consume DLQ Read failed records Inspect
Fix/Transform Correct payload Or code
Republish Back to source topic Retry

Example: Replay DLQ

for (var r : dlqConsumer.poll(d)) {
  String fixed = repair(r.value());
  producer.send(new ProducerRecord<>("orders", r.key(), fixed));
}

9. Setting DLQ Retention

Aspect Description Detail
Longer Time to investigate Days/weeks
retention.ms Per-topic setting Override
Balance Disk vs recovery window Tune

Example: 14-day DLQ retention

kafka-configs.sh --bootstrap-server localhost:9092 --alter \
  --entity-type topics --entity-name orders.dlq \
  --add-config retention.ms=1209600000

10. Implementing Circuit Breaker

Aspect Description Detail
Trip Stop on high failure Threshold
Pause Hold consumption consumer.pause()
Resume After recovery probe Half-open

Example: Pause on breaker open

if (breaker.isOpen()) {
  consumer.pause(consumer.assignment());
} else {
  consumer.resume(consumer.assignment());
}

Was this article helpful?