Aggregate instance getting created for every command issued

Hello Team,

Question: Is it by design that, for each new command issued, all the events until the snapshot are everytime loaded and replayed from the store on newly created aggregate, before applying that command on it ?

Below is the explanation of the scenario -

I have an aggregate with say 3 command ( Cmd1, Cmd2, Cmd3 ) and each of which would trigger respective events ( Event1, Event2, Event3 ) like below.

@Aggregate
class TestAggregate {

   public TestAggregate(){
       System.out.println("Aggregate created");
   }

   public void on(Cmd1 command){ 
      System.out.println("Inside Cmd1 handler");
       Aggregate.apply(new Event1(..));
   }

   public void on(Event1 event){
     System.out.println("inside Event1 handler");
   }

     public void on(Cmd2 command){ 
      System.out.println("Inside Cmd2 handler");
       Aggregate.apply(new Event2(..));
   }

   public void on(Event2 event){
     System.out.println("inside Event2 handler");
   }

  public void on(Cmd3 command){ 
      System.out.println("Inside Cmd3 handler");
       Aggregate.apply(new Event3(..));
   }

   public void on(Event3 event){
     System.out.println("inside Event3 handler");
   }
}

When the Cmd1 is issued below are the logs created

System.out.println("Aggregate created");
System.out.println("Inside Cmd1 handler");  
System.out.println("inside Event1 handler");

When the Cmd2 is issued below are the logs created

System.out.println("Aggregate created");
System.out.println("inside Event1 handler");
System.out.println("Inside Cmd2 handler");  
System.out.println("inside Event2 handler");

When the Cmd3 is issued below are the logs created

System.out.println("Aggregate created");
System.out.println("inside Event1 handler");
System.out.println("inside Event2 handler");
System.out.println("Inside Cmd3 handler");  
System.out.println("inside Event3 handler");

Hi @mnkartik,

I am not one the Axon developers, but I hope it’s okay if I answer the question.

Yes it is. This is what event sourcing (as implemented by the Axon team) actually is. The so called command model (which is used to check whether the aggregate is in a state that allows the execution of the command) is “replayed” each time you want to execute a command (either based on the events or - as you already stated - based on the snapshots). This is also described in more details here: Event Sourcing - Axon Reference Guide

CQRS usually separates the command model (also called write model) from the query model (also called read model).

Best regards

Nils

3 Likes

Hi @nils-christian

This I have observed when the logs were applied to the event handlers, which were getting logged at the time of replay.

Q: Since there would not be any such configuration to disable this feature, the only option is to enable snapshoting right, so that less number of events would be replayed everytime the command is issued. Is it ? or do we have any other approach ?

Q: And since the replay is occurring eveytime, its not wise to have the logging enabled esp on the event handlers, due to the confusion it creates when debugging. What is the solution for logging the aggregates ?

Hi @mnkartik,

About the first question: If you are working with aggregates this is indeed the way to go. In our own experience: The replaying only creates issues if your events are really fat (e.g. containing binary files), in which case you should probably consider to move the larger payloads our of the events. If you have a lot of events and the replaying causes performance issue, you would probably want indeed to use snapshotting. If you have a lot of events to build your aggregate state, you might want to reconsider the design of your aggregate.

You could also move your logic into other components which handle the commands if you do not really want to use event sourcing. That said, I would still recommend to start with the “default” Axon way and use event sourcing aggregates without snapshots (in the beginning). If you encounter performance issues later, you can still use snapshotting etc.

About the second question: In our own experience it is almost never useful to log the event sourcing handlers. Instead focus on the command handlers to log important information (e.g., an action that has been performed) and on tests.

Best regards

Nils

Thank you very much @nils-christian.

Hi @mnkartik,

Thanks @nils-christian for all the correct answers!
Let me just add a bit more to it =)

Indeed, @EventSourcingHandlers are called to ‘rehydrate’ you @Aggregate every time a new Command is fired towards that specific Agrgegate. As @nils-christian correct pointed out, this is the pattern called Event Sourcing where Events are really your source of truth.
So to your first question, yes… this is normal and expected.

For the follow up questions, I wouldn’t start with Snapshot until the need for that really arises.
Snapshot can be seen as an improvement, and as every improvement, shouldn’t be done prematurely - it all comes with a cost and better only deal with that when you really need it!

And for logs, when using Event Sourcing, I would say the most important part is the @CommandHandlers because they are responsible for your business logic. Once the Command is allowed and you apply an Event, that is a fact and will be stored forever on your Event Store - there is no way back =)
So, you really need and want to pay attention to what happens inside your Command Handler and logs would be benefical there so you can better understand why a given Command failed for example.

Hope it helps to clarify your doubts and feel free to ask more questions if needed.

KR,

Thank you @lfgcampos for the information. It makes sense to log only command handler and logging event handler will not help as its going to be replayed and would be confusing while debugging.

From debugging standpoint, suppose if ones does not want to expose the Axon Server UI to developer(s), the only system would be left would be central logging system ( say ES+Kibana ), where command handler logs are visible, but for events also to be logged ( only once ) in this same centralized log systems, would we need to add a new event handler specifically to log those events into ES+Kibana or do we have any other option ?


Kartik

Hi @mnkartik,

So, the ones that does not make sense is the @EventSourcingHandlers which are present on Aggregates and will only mutate it’s own properties and nothing else.
In other words, there are no benefit in logging this as you should be able to see what happened through the chain of Events as in DDD, Events should really have a meaning!

If you are talking about @EventHandlers, there is nothing wrong with logging things there as that is part of your Query side (if we talk about CQRS for example).

If you really really need any kind of status or logs, you can think about logging the current state of your Aggregate when you are handling Commands → but just keep in mind that you can have certain values you don’t want to see on your logs.

Let me know if that helps you further!

KR,

True, its not only the properties of aggregate getting logged in command handler to be masked, but also holds good for both command as well as event ( inside @EventHandler ).

Thank you @lfgcampos for the information.


Kartik

@lfgcampos I am not sure whether I could ask the design reasons in this forum.

But had a doubt on that as what is the major benefit we see that for every command issued, a new aggregate instance is created and events are applied and not keep the same aggregate object as is and apply new commands to it, apart from the fact that replaying would ensure consistent state on which command is applied, probably version conflicts are also solved and yes JVM garbage collection has become very much efficient and memory is cheaper these days.

Would this design still be working well, if any system is facing heavy command inflow for an aggregate being issued and the aggregate have a heavy state involved ( assuming such scenario ). Do you have any performance tests performed.

Let know if any such detail is already part of the documentation, I would go through it, instead of reiterating the same here.

@nils-christian It’s more than OK to answer questions. It’s much, much appreciated!

We started Discuss with the idea of having a place where developers interested in DDD, CQRS, Event Sourcing, and Axon technologies can help each other. While we at AxonIQ try hard to have our fair share in that goal, the last thing we want is to exercise a monopoly on knowledge and answers. We are fully aware that many of the folks here are knowledgeable and experienced developers with lots to share. We want to encourage everyone to answer and discuss all topics. We are very grateful for all of your contributions.

Hello @mnkartik, of course you can ask this kind of questions here.

As you pointed out, there are no major drawbacks and lots of benefits, already listed by you - consistent state, no version conflicts, better garbage collector, etc.
I can also add location transparency which makes your system pretty easy to scale for example, but also to ‘plug in’ new components as the need arise.

This scenario works well but it depends on your design - assuming you have plenty of Aggregates, it should scale without a problem. There are ways to make it ‘faster’ if needed (Snapshotting and Caching) but you shouldn’t care about that beforehand.
If you think about it, most of the bank systems are like that where you usually don’t have your current ammount saved somewhere but derived from your past events (transfers, deposits and withdraw). Same goes for a git repository where every commit is an Event!
Again, those are examples but everything depends on your design in the end.

For your example, usuallly an Aggregate won’t have such a ‘heavy state’ as it should only store what is important for making decisions and nothing else! So that is completely fine and should work without problems on such scenario.

Feel free to ask more about it.

KR,