Skip to content
Get started
Get started
DLQ Operations: Filter, Retry, Remove, Purge
View Markdown
guide · dead letter queue

Read it, retry it, clear it.

The four things you actually do with a Dead Letter Queue: narrow it down to the entries you care about, put a subset back, check whether the pile is growing, and empty it when the cause is fixed.

await queue.getDlqAsync({ reason: 'max_attempts_exceeded' }); // by emitted reason
await queue.getDlqAsync({ olderThan: Date.now() - 86400000 }); // older than 24h
await queue.getDlqAsync({ newerThan: Date.now() - 3600000 }); // last hour
await queue.getDlqAsync({ retriable: true }); // auto-retry is due now
await queue.getDlqAsync({ limit: 10, offset: 20 }); // pagination

The Bun async API applies reason, time, due-retry, expiry, limit, and offset filters server-side in both embedded and TCP modes. The HTTP endpoint currently supports only limit and offset; external clients must filter that page locally. retriable: true means nextRetryAt is already due, not merely that the entry has retry budget remaining.

queue.retryDlq(); // retry everything
queue.retryDlq('job-123'); // retry one job
queue.retryDlqByFilter({ reason: 'stalled' }); // TCP is fire-and-forget
const filtered = await queue.retryDlqByFilterAsync({ reason: 'stalled' }); // authoritative count
const n = await queue.retryDlqAsync(); // retry and get the count (TCP too)
const stats = await queue.getDlqStatsAsync();
console.log(stats.total); // total entries
console.log(stats.byReason); // { max_attempts_exceeded: 5, stalled: 2, ... }
console.log(stats.pendingRetry); // entries whose auto-retry time is due

A simple alert loop:

setInterval(async () => {
const stats = await queue.getDlqStatsAsync();
if (stats.total > 100) alertOps('High DLQ count', stats);
}, 30000);

Use synchronous getDlqStats() for a Bun embedded snapshot and getDlqStatsAsync() for an authoritative Bun result in either runtime. The other SDKs do not expose a stats helper yet; the HTTP result is authoritative.

const removed = await queue.removeDlqJob('job-123');
// true: the selected DLQ entry was deleted
// false: it was already absent

removeDlqJobAsync(id) is an explicit alias with the same Promise<boolean> contract. The operation does not retry the job. It removes the durable entry and terminal auxiliary state before resolving, including any recovered duplicate rows for the same queue and job ID. Broker and persistence errors reject the Promise; only a successful miss resolves false.

const purged = queue.purgeDlq(); // permanently deletes all entries
const n = await queue.purgeDlqAsync(); // same, but waits and returns the count (TCP too)
DLQ Operations from the Queue ObjectThe same operations from an existing Queue instance
Dead Letter QueueWhat the DLQ is, and a first look at what failed
Automatic DLQ Retry with BackoffLet bunqueue re-queue dead entries on a backoff
DLQ ConfigurationautoRetry, maxAge, maxEntries and the defaults
DLQ ReferenceFailure reasons, entry shape, every DLQ method