Beanstalkd bury is a dead letter state built into the server

Most brokers make a dead letter queue a convention you assemble from routing rules; Beanstalkd has it as one of three verbs.

$job = $queue->reserveWithTimeout(5);

try {
    $this->handle($job->getData());
    $queue->delete($job);            // done
} catch (Transient $e) {
    $queue->release($job, 1024, 60); // back to the tube in 60s
} catch (Throwable $e) {
    $queue->bury($job);              // set aside for a human
}

A buried job sits in its own state until somebody kicks it back, and kick takes a count so a batch can be retried after a fix. The distinction between release and bury maps directly onto transient and permanent failure, which is a distinction most handlers should be making anyway. A reserved job returns to the ready queue automatically when its time-to-run expires, so a crashed worker needs no recovery timer at all — which is the smallest correct queue I know of.