[GH-ISSUE #1078] What's the correct way to handle dead-letter queue #2540

Open
opened 2026-03-15 20:49:25 +03:00 by kerem · 1 comment
Owner

Originally created by @tryffel on GitHub (Oct 14, 2025).
Original GitHub issue: https://github.com/hibiken/asynq/issues/1078

Hi,

it would be helpful to have functionality for dead-letter queue.
Example use case would be to retry task N times and after that, run specific callback to handle permanent failure in application logic.
Now this is not possible since the task handler doesn't have visibility into task's failure count.

A good way to handle this could be either to have separate deadletterqueue-handler similar to existing error handler that is called before moving the task into archive: TaskArchived(task).
Alternatively, call the same task handler, but expose the retry count / state transition info into task type so that the handler can handle the case with e.g. if task.IsArchived().

Originally created by @tryffel on GitHub (Oct 14, 2025). Original GitHub issue: https://github.com/hibiken/asynq/issues/1078 Hi, it would be helpful to have functionality for dead-letter queue. Example use case would be to retry task N times and after that, run specific callback to handle permanent failure in application logic. Now this is not possible since the task handler doesn't have visibility into task's failure count. A good way to handle this could be either to have separate deadletterqueue-handler similar to existing error handler that is called before moving the task into archive: `TaskArchived(task)`. Alternatively, call the same task handler, but expose the retry count / state transition info into task type so that the handler can handle the case with e.g. `if task.IsArchived()`.
Author
Owner

@RychEmrycho commented on GitHub (Dec 11, 2025):

IMO, archived task is basically the DLQ implementation of asynq.

regarding the requested functionality, seems like it can be generalized into a task status change callback, not specific to archived status. i can think of something like this, should be sufficient to inspect task details.

asynq.NewTask("feed:import", nil, 
        asynq.MaxRetry(5), 
        asynq.StatusChangeCallback(func(info asynq.TaskInfo) {
                // do something
        })
)

its just a simple func which provides the task info and should work perhaps in a best attempt fashion / fire & forget? so it shouldnt block the task processing, but im not sure what kind of edge cases that might happen

<!-- gh-comment-id:3642883757 --> @RychEmrycho commented on GitHub (Dec 11, 2025): IMO, archived task is basically the DLQ implementation of asynq. regarding the requested functionality, seems like it can be generalized into a task status change callback, not specific to archived status. i can think of something like this, should be sufficient to inspect task details. ``` asynq.NewTask("feed:import", nil, asynq.MaxRetry(5), asynq.StatusChangeCallback(func(info asynq.TaskInfo) { // do something }) ) ``` its just a simple func which provides the task info and should work perhaps in a best attempt fashion / fire & forget? so it shouldnt block the task processing, but im not sure what kind of edge cases that might happen
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/asynq#2540
No description provided.