Axon 4.6 - Dead Letter Processing Questions


I played a little bit with the new dead letter queue in Axon 4.6 and came across some parts that seemed a little bit, well, off to me. I would like to discuss those things. Maybe I am just misunderstanding some parts or maybe I just had different expectations (or maybe the documentation has to be tweaked a little bit?)

  1. The documentation states that a call to (for example) sequencedDeadLetterProcessor.processAny( ) processes a dead letter entry. So I assume one would have to build something like a recurring task to start the dead letter processing? Looking at the dead letter queue concept from the outside, I expected the processing to be performed automatically by the framework. Just like the event processing. Why do I have to call the processing manually (or do I? The documentation does not state that clearly to me)?

  2. What exactly is the task of a SequencedDeadLetterProcessor? My first thought was (also based on the name) that it actually does process the dead letters, but it gets a predicate as a parameter. The actual processing seems to be done by the regular event handlers. There isn’t an example for an implementation within the documentation, so I just don’t know what to implement in the process method.

  3. The choice of using an interface for the SequencedDeadLetterProcessor seems orthogonal to other concepts in the Axon framework. Usually we have annotations to mark methods for processing certain elements (event handlers, reset handlers, …). Why use an interface for this? Because it is more of a technical aspect?

  4. The documentation does not state what happens when you reset the tokens of an event processor with dead letter queue. I assume that the queue is cleared (based on the implementation of DeadLetteringEventHandlerInvoker), but it would be nice if this would be a documented behaviour.

Thank you and best regards


Hello @nils-christian, thanks for the feedback! There have been quite a few iterations of the DLQ to get to where we are now, and I can explain why we made certain choices.

  1. You are correct that it’s up to you to initiate a retry. We might add an automatic mechanism in 4.7.0, but by not including this by default we give the user full control over when the messages are retried.

  2. The SequencedDeadLetterProcessor is in essence the event invoker which is compatible with retrying messages in the DLQ. The only one currently in the framework is the DeadLetteringEventHandlerInvoker. The predicate will receive the first message of each sequence in the queue, to determine which sequence to start retrying. It’s correct that the processing is done by the regular event handlers, through this DeadLetteringEventHandlerInvoker.

  3. The SequencedDeadLetterProcessor is an interface so the user does not have full access to the DeadLetteringEventHandlerInvoker immediately. This keeps our API a little clearer, or at least that was the intention.
    Annotations cannot be used here, since it’s not a handler or something similar. It’s the initiator of a process, which in turn calls the registered handlers which would also be used when handling the message regularly.

  4. You are correct, it would be great if the documentation shows this. I will create a PR for that this week.

Please let me know if there are further questions or suggestions. I hope my answers make it a little bit clearer.

Kind regards,


As a small addition to my previous answer, I just published a blog explaining the new DLQ feature. It should give a great introductory explanation, hope it helps!

I just read your blog post. Just would like to point you to an error:

Should be “a user created a ship without a name” or “a user created a ship with an empty name” :wink: