# Automatic DLQ Retry

How bunqueue automatically redelivers DLQ jobs with a bounded exponential policy that survives SQLite or PostgreSQL broker restarts.

Canonical: https://bunqueue.dev/guide/dlq/auto-retry/

---

import { Tabs, TabItem } from '@astrojs/starlight/components';

<div class="bq-wrap bq-hero">
  <span class="bq-eyebrow">guide · dead letter queue</span>
  <h1 class="bq-hero-h1 bq-bench-h1">Retries that happen <em>without you.</em></h1>
  <p class="bq-hero-sub">Some failures are transient. Auto-retry puts a due DLQ entry back into its queue, preserves its failure history, and stops after the configured retry budget.</p>
</div>

## Automatic Retry

With `autoRetry` enabled, a new DLQ entry receives a `nextRetryAt` equal to its
entry time plus `autoRetryInterval`. The broker's DLQ maintenance task checks
due entries every 60 seconds by default, removes each due entry from the
DLQ, advances its automatic retry counter, resets the job's normal attempt and
stall counters, and re-queues it. SQLite-backed queues perform the DLQ deletion
and waiting-job insertion atomically; PostgreSQL performs the corresponding
generation transition in one transaction under the shared dependency lock plan.

<Tabs syncKey="lang">
<TabItem label="Bun">

```typescript
queue.setDlqConfig({
  autoRetry: true,
  autoRetryInterval: 60000, // base delay: 1 minute
  maxAutoRetries: 3,
});
// In TCP mode, prefer await queue.setDlqConfigAsync(...) to confirm the write.
```

</TabItem>
<TabItem label="Node.js / Deno">

```typescript
await queue.setDlqConfig({
  autoRetry: true,
  autoRetryInterval: 60000, // base delay: 1 minute
  maxAutoRetries: 3,
});
```

</TabItem>
<TabItem label="Python">

```python
# Config keys are the wire names (camelCase)
queue.set_dlq_config({
    "autoRetry": True,
    "autoRetryInterval": 60000,  # base delay: 1 minute
    "maxAutoRetries": 3,
})
```

</TabItem>
<TabItem label="PHP">

The PHP SDK has no config helper yet. Set the server-side policy through HTTP:

```bash
curl -X PUT http://localhost:6790/queues/emails/dlq-config \
  -H 'content-type: application/json' \
  -d '{"autoRetry":true,"autoRetryInterval":60000,"maxAutoRetries":3}'
```

</TabItem>
<TabItem label="Go">

The Go SDK has no config helper yet. Set the server-side policy through HTTP:

```bash
curl -X PUT http://localhost:6790/queues/emails/dlq-config \
  -H 'content-type: application/json' \
  -d '{"autoRetry":true,"autoRetryInterval":60000,"maxAutoRetries":3}'
```

</TabItem>
<TabItem label="Rust">

The Rust SDK has no config helper yet. Set the server-side policy through HTTP:

```bash
curl -X PUT http://localhost:6790/queues/emails/dlq-config \
  -H 'content-type: application/json' \
  -d '{"autoRetry":true,"autoRetryInterval":60000,"maxAutoRetries":3}'
```

</TabItem>
<TabItem label="Elixir">

The Elixir SDK has no config helper yet. Set the server-side policy through HTTP:

```bash
curl -X PUT http://localhost:6790/queues/emails/dlq-config \
  -H 'content-type: application/json' \
  -d '{"autoRetry":true,"autoRetryInterval":60000,"maxAutoRetries":3}'
```

</TabItem>
</Tabs>

The config lives server-side per queue, so setting it from any client applies
to jobs produced and consumed in every language. The policy, retry counter,
complete failure history, original entry/expiry times, and next retry time all
survive a SQLite or PostgreSQL broker restart.

The first retry becomes due after the base interval. Each dispatch increments
`retryCount`; if the redelivered job fails again, its next delay follows
`autoRetryInterval * 2^(retryCount - 1)`. Once `retryCount` reaches
`maxAutoRetries`, `nextRetryAt` becomes `null` and automatic redelivery stops.

:::note[Maintenance cadence and manual retries]
A due retry may start up to one maintenance interval after `nextRetryAt`; the
default maintenance interval is 60 seconds. Calling a manual `retryDlq` API is
an operator-directed new generation: it clears the automatic retry chain and
normal attempt/stall counters before re-queuing the job.
:::

## Where to go next

|                                                           |                                                     |
| --------------------------------------------------------- | --------------------------------------------------- |
| [DLQ Operations from the Queue Object](/guide/queue/dlq/) | The same operations from an existing Queue instance |
| [Dead Letter Queue](/guide/dlq/)                          | What the DLQ is, and a first look at what failed    |
| [DLQ Operations](/guide/dlq/operations/)                  | Filter, retry selectively, check health, purge      |
| [DLQ Configuration](/guide/dlq/configuration/)            | autoRetry, maxAge, maxEntries and the defaults      |
| [DLQ Reference](/guide/dlq/reference/)                    | Failure reasons, entry shape, every DLQ method      |