What is Poison Message?
Also called poison pill message.
A poison message is a queued item that a consumer cannot process successfully no matter how many times it retries, because the failure is caused by the message itself rather than by a transient condition. Left unhandled, it is redelivered indefinitely, consuming capacity and blocking progress for other work.
Causes are structural rather than environmental: a malformed payload that fails parsing, a reference to a record that has since been deleted, a field value outside the range the consumer accepts, or a payload large enough to exhaust memory. Each triggers the same failure on every attempt. Retry logic designed for transient faults makes these cases worse by guaranteeing repetition without progress.
The damage extends past the single message. In a strictly ordered partition, a stuck item halts everything behind it. In a shared pool, repeated failures occupy workers, inflate error rates, and can trigger alerts that mask unrelated problems. When each attempt calls a metered model, an unbounded retry loop over one bad item converts a data defect into a continuing cost.
The standard containment pattern is a delivery counter with a threshold: after a set number of attempts, the message is moved to a dead-letter destination and the main flow proceeds. This is a design decision to lose ordering and immediate completeness for that item in exchange for overall liveness. It must be paired with visibility, since a dead-letter store nobody inspects merely hides the defect.
Distinguishing poison from transient failure is not always clean. A dependency outage produces identical repeated failures that would succeed later, so an aggressive threshold can dead-letter a large volume of otherwise valid work during an incident. Classifying by error type, where parse and validation errors go straight to dead-letter and dependency errors get patient retries, handles both cases better than a single counter.
Key points
- Fails on every attempt because the message itself is the cause
- Retry logic for transient faults amplifies the problem
- Blocks ordered partitions and consumes shared worker capacity
- Attempt thresholds move it to a dead-letter destination
- Classify by error type so outages are not dead-lettered wholesale
In practice
A document processing queue receives a file whose declared type is PDF but whose bytes are a corrupted archive. The extraction worker throws on every attempt, and because each attempt also issues a model call, the item burns cost while looping. After the delivery count reaches five, the broker routes it to a dead-letter queue, an alert fires on queue depth, and normal throughput resumes.