Engineering note · 4 of 6

Crash loops must end.

Generation fencing stops a late runner from winning. The poison pill stops a cursed job from reclaiming forever — after reclaim.max_retries, the run is terminal error, the thread is released, and hooks fire. No infinite re-enqueue.

What “poison” means here

Not content filtering. A job that keeps killing runners (OOM, bad tool, broken graph) would otherwise bounce reclaim → dequeue → crash → reclaim… forever, burning capacity and drowning operators in noise.

Config

Applies on Redis, NATS, and Kafka — same ceiling, no transport-only asymmetry. Distinct from live cancel and from Admin kill switches.

How it pairs with fencing

Fencing answers: “which attempt is allowed to write?” The poison pill answers: “how many attempts are allowed at all?” You need both — otherwise a well-fenced crash loop still never dies.

Operators get a hard stop they can explain: “it failed after N reclaims,” not “the queue is haunted.”

Fencing Subscribe-before-enqueue createRunCtx Poison pill FinOps holds Postgres RLS grant