Why does the event store save events *from* aggregates rather than events *to* aggregates?

I’m curious about a design decision in Axon.

An event gets persisted to the event store if it’s sent by an aggregate. But aggregates can listen for and react to events from any source, and those events can potentially cause state changes. A saga could publish an event with a @TargetAggregateIdentifier field as it coordinates work related to a particular aggregate (for example, a “warehouse has acknowledged this order” event) but that event won’t be persisted even if there’s a listener for it on the targeted aggregate. And events published by aggregates always get persisted even if they’re only ever consumed by other parts of the system and have no bearing on the aggregate’s state.

This seems backwards to me and I’m wondering what I’m missing. My intuition is that you’d want to persist any events that are passed to an event handler on an aggregate, regardless of where they came from, since otherwise replaying the events from the event store won’t necessarily result in the aggregate being in the same state it was the first time around.

Hope someone can explain where I’m leading myself astray here. I’m ending up writing aggregate command handlers that do nothing but apply() the events I wanted to send in the first place, which seems like a sign I’m fundamentally misunderstanding something.


it seems like you’re confusing commands and events. Aggregates will only react on events generated by that same aggregate instance. However, they can react to commands from every source. @TargetAggregateIdentifier is an annotation that is placed on Commands, not Events.
Events by aggregates are persisted only when using Event sourcing. They are stored, so that you can reconstruct the aggregate instance from the events that it generated.

Having command handler methods in an aggregate that do nothing else than apply() an event, isn’t a strange thing. However, if your aggregate has nothing else than that, you might have to reconsider some EventSourcing (or even CQRS) choices that you have made.



You’re exactly right. Early on in my experimentation with Axon I seem to have put a @TargetAggregateIdentifier annotation in an event class by mistake and apparently I managed to convince myself it was a meaningful thing. Thanks for the clarification; it makes more sense now.