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());
}