Deadlines vs events for scheduling activities

Earlier, I posted a question about how to test scheduled events.

I now realize I can’t answer a more fundamental question: what should motivate me to use events vs deadlines, for example to schedule future activities.

My scenario:

I am working on an application that needs to

  • schedule activities for its users based on some business rules
  • remind the users to perform these activities at specific predefined times
  • record the time the user took responding to the reminder
  • have some other system score user’s behavior and perhaps give them money as a reward.

I modeled application user as an aggregate root User. Among other things, I made it responsible for creating user activity schedule as it has all the knowledge to do it. I would also like it to trigger notifications, to be acted on by some external event handler that knows the notification machinery.
My choices:

  • schedule an event to be published at the time the user needs a reminder
  • schedule a deadline to come due at the time of reminder to publish that event immediately
  • ??

My current incomplete understanding:

Deadlines

Deadlines seem to fit well in the narratives like “whenever the customer has not submitted their application in 30 days…” or “whenever the invoice has not been paid by the 15th of the month”. Sounds like event storming policies.

These narratives feel natural for describing long(-ish)-running business processes expecting that an external actor does something by a certain time, defining the policy to use if the actor has not done so. In other words, the literal meaning of “deadline”.

Also, these kind of processes are convenient to model with sagas.

Possible solution

I could choose deadlines to represent reminders, setting up a saga for the duration of the schedule, complete with a deadline for each reminder. The saga would then emit commands to User when a deadline elapses… Doesn’t sound right as I don’t need to coordinate this across multiple aggregates, plus unnecessary moving parts.

Should I then have my User aggregate set up a bunch of deadlines for itself, in command handler responding to the command telling it to create the user’s schedule? Then, in deadline handler, I could publish an event to trigger a reminder every time a deadline comes due.

Events

Events, on the other hand, feel to me more natural to use as a scheduling mechanism for (shorter-term?) reminders, timers, recurrent activities: “remind the user do take their blood pressure meds at 9:00am every day”. Notice the absence of not: we have a business process requiring something to happen at a regular time as opposed to no later than…. Not a policy.

Possible solution

I am tempted to schedule user activities for the known future in the appropriate command handler as events. Then, whenever such event is published, my aggregate will take note, and once the user responded to the reminder, it will publish another event telling the interested parties how long the user took to respond.

That’s where doubt creeps in: is this a misuse of events? One sign of this is the difficulty naming such events: UserReadyToBeNotified? NotificationRequested? Should I just publish the schedule and have some other component, unrelated to the user, do all the scheduling?

The question

To pick a scheduling mechanism appropriate for my situation, I would like to know how the authors of Axon Framework intended to use deadlines vs scheduled events. I have not been able to find a good answer either in Axon documentation or on this forum.

So:

  • what kind of scenarios are better served by deadlines?
  • what kind of scenarios are better served by scheduled events?

Thank you very much,
Vlad

Hi Vladimir,

the actual story is that Scheduled Events was the first feature implemented. However, we noticed that it’s not always desired to have these Events stored (perpetually) in the Event Store. That’s when we came up with the Deadline API. It’s a very similar API with one difference: the Deadline Events will only trigger the component that scheduled the deadline. They are not visible for other components.

So in terms of functionality, they’re basically two different ways of achieving the same thing. I’d say the main question should be: “do I want to remember that this specific event occurred in the past”? Very often, the answer will be no. For example, the fact that the payment date for an invoice expired is irrelevant. The prior events will already tell that store. However, the fact that the invoice has become overdue (because the invoice date expired and the invoice is still unpaid), is important. So the “payment date” is a deadline, and the “payment overdue” event is a Domain Event triggered by that deadline.

Hope this makes sense.

Hi Allard,

Thank you very much. Definitely makes sense.

Then: should I think of deadlines as scheduled commands?

I have a couple of scenarios I am trying to find appropriate fit for.

  • schedule a reminder in the future. When the moment arrives, I want my aggregate to publish an event that it will ignore (by means of not having an event sourcing handler), but that another component, e.g. notification service, will act on. This is a job for a deadline, right?
  • schedule a future domain event: the user enrolls in a program lasting N weeks. I want to schedule an event, UserGraduatedFromProgram, on the last day of that program. This will probably start a graduation saga coordinating this process across a couple of aggregates. In this case I probably want an event, not a deadline, right?

I could implement the latter via a deadline that will trigger the event, but I think it will just add an extra step.

Thank you again,
Vlad

Seeing deadlines as scheduled commands is fine way of putting it if you ask me.

Schedule a reminder in the future. When the moment arrives, I want my aggregate to publish an event that it will ignore (by means of not having an event sourcing handler), but that another component, e.g. notification service, will act on. This is a job for a deadline, right?

Agreed, this would work as a deadline. The aggregate handles the deadline, adjusts its state “to ignore” and other components can react to the published event from the aggregate.

Schedule a future domain event: the user enrols in a program lasting N weeks. I want to schedule an event, UserGraduatedFromProgram, on the last day of that program. This will probably start a graduation saga coordinating this process across a couple of aggregates. In this case, I probably want an event, not a deadline, right?

I agree this doesn’t sound like a deadline. Also because it sounds like a milestone occurrence in your system other parties would be interested in too. So using the EventScheduler to mark this occurrence sounds fine to me.