Queues & Background Processing in Depth · Background Job Processing

Poison Messages and Head-of-Line Blocking

Stop one bad message from blocking a partition or queue.

A poison message fails every time it's processed. In ordered systems (Kafka partitions, FIFO groups) it blocks everything behind it (head-of-line blocking). Mitigations: bounded retries then DLQ/DLT, non-blocking retry topics (retry-5s, retry-1m topics) so the main partition keeps flowing, validating schemas at the producer, and quarantining by key when order must be preserved per entity.

Handling poison messages

Strategy Keeps flowing? Preserves per-key order?
Retry in place forever No (blocked) Yes
Retry N times then DLT After N attempts Mostly (skips the bad message)
Non-blocking retry topics Yes No (retried message processed later)
Park key (quarantine) Yes for other keys Yes (key paused until fixed)
# Spring Kafka non-blocking retries
@RetryableTopic(attempts = "4", backoff = @Backoff(delay = 1000, multiplier = 5.0),
                dltTopicSuffix = ".DLT", autoCreateTopics = "true")
@KafkaListener(topics = "orders")
public void onOrder(OrderEvent event) { ... }
# creates orders-retry-0, orders-retry-1, ..., orders.DLT

Common pitfalls

  • Blocking a whole partition for one bad message.
  • Retry topics breaking ordering assumptions silently.
  • Producers sending schema-invalid messages.

Key points

  • Bound retries
  • Non-blocking retry topics when order allows
  • Validate at the producer

Further reading: Spring Kafka: Non-blocking retries

Practice questions

What is head-of-line blocking in a Kafka partition?

Answer

A message that keeps failing stops the consumer from advancing the partition's offset, so all later messages in that partition wait.

What's the trade-off of non-blocking retry topics?

Answer

The main flow continues, but the failed message is processed later, out of order relative to subsequent messages for the same key.

Open in the app to mark lessons complete, take notes and track your progress.