The dead letter queue (DLQ) captures jobs that have permanently failed after exhausting all retry attempts.
How entries are created01
When a job's RetryCount reaches MaxRetries and the handler still returns an error, the executor calls dlq.Service.Push to create a DLQ entry preserving the full context:
Original job name, queue, and payload
Final error message
Total retry count and max retries
Scope app/org IDs
The job state is set to failed and an ext.JobDLQ event fires.
Listing DLQ entries02
entries, err := eng.DLQService().DLQStore().ListDLQ(ctx, dlq.ListOpts{
Limit: 50,
Offset: 0,
})Or use the admin API:
GET /v1/dlq
GET /v1/dlq/:entryId
GET /v1/dlq/countReplay03
Replay re-enqueues a DLQ entry as a new pending job with the original payload. The ReplayedAt field is set on the DLQ entry.
Via admin API:
POST /v1/dlq/:entryId/replayPurge04
Remove all DLQ entries:
POST /v1/dlq/purgeThis is destructive and irreversible. Use with caution.
DLQ service05
The dlq.Service is accessible via the engine:
svc := eng.DLQService()
// Push is called automatically by the executor.
svc.Push(ctx, failedJob, err)
// Access the store directly for list/count/purge.
svc.DLQStore().ListDLQ(ctx, opts)
svc.DLQStore().PurgeDLQ(ctx)