Always active saga

I’m a student and a few days ago I was introduced to Axon and DDD.
Is there a way to have a saga that will always be active, or is there an event that will start it with the application? I hope I’m wording this right.
I need it to be listening to events about messages and then send notifications every half an hour about the new ones, but I don’t know how to start it because I don’t need it to start for the first time when a message is sent, I need it to be already listening. I’m not sure if saga is the right thing to use here, too, so if it isn’t, what could I use?

Hi Arya,

Great to hear that you’re using the framework as a student!

To answer your question though, I think you shouldn’t be looking at Saga’s to solve your problem.

A regular Event Handling Component would be far better suited for the scenario you provide.

That component/class would contain the required @EventHandler annotated functions for the events you’re interested in, and very likely store them through some mechanism.

Additionally, that component (or a different service) would be triggered every x-minutes (30 in your case, as you’re stating ‘every half an hour’) to query all the new messages from your preferred storage mechanism.

Then you’d obviously be able to send the notification of all the new events that have been handled.

Very likely, you’d remove the messages you’ve send notifications for after that notification has been send.

Hope this helps you somewhat Arya!



Hi Arya, Steven,
I agree that some other component might be used as well, but there is one thing that Saga aboard out-of-the-box => persistence of the state and ability to ‘continue’ after restart. Achieving that with some other component would be quite more effort I think.

To achieve this kind of ‘singleton’ saga, you can make saga that listens to these events on sent messages, and you can associate it to something that is same for all these events, like class name or some extra added hardcoded field.

This way single sage instance would live and serve all these events, it can be mixed with quartz scheduler to fire on 30 minutes and so on.

So, you can pick from these alternatives.


Here’s an approach we’ve used successfully to set up a singleton saga.

Publish an event on the event bus when the application starts. This should include a field with a fixed value, e.g.,

public class ApplicationStartedEvent {
public String getFixedValue() {
return “fixedValue”;


Then, in your saga, listen for this event:

public class MySaga {
private boolean initialized = false;

@SagaEventHandler(associationProperty = “fixedValue”)
public void on(ApplicationStartedEvent event) {
if (!initialized) {
// Do your initial setup here, e.g., call associateWith()
// or schedule some events


There will only ever be one instance of the saga because, once the saga is created initially, the event will match the existing instance.

If you have a lot of singleton sagas in your system, it’s probably a design smell, but they can be useful as a way to take advantage of Axon’s built-in infrastructure, even if it might technically not be pristine DDD. For example, we use singleton sagas to manage some concurrency limits that have to apply across our entire application rather than per-host. It’s definitely possible to build that kind of thing some other way, but we’d end up having to reimplement some of the logic that’s already built into Axon.

I hit “Post” before proofreading my code. Obviously, you’d want to set “initialized” to true inside the “if” statement in the saga code.

Hi all,

We’ve been working on a feature called Deadline API. I’m not sure whether it’s well suited for the problem you have, but I think it is worth mentioning since it deals with invoking the deadline handlers on your sagas or aggregates (and can be extended for different components).

So, when handling commands / events you can schedule a deadline to be triggered after 30 minutes (or whatever). When you handle this deadline you can send the notifications. Of course, the deadline can be cancelled if necessary.

Hope this helps a bit!