CQRS – Domain state
This morning Aaron Jensen asked a really interesting question on Twitter “Should Aggregate Roots en Entities always keep their state if it is not needed for business decisions? Is firing events and relying on the reporting store enough?”. He really made me think, Aaron thanks for that!
So for example you have some behavior on your domain that gets called when a customer moves, this behavior will publish a Customer Moved event containing the new address. If the domain does not use the address information for any decision making, does it then need to be persisted in the aggregate root?
I guess it would greatly depend on whether or not you are using Event Sourcing to persist your published events (this is what I would suggest). If you do then I don’t see a problem in skipping storing the address information in the aggregate root. Because if at a later time you need the address information to make some decisions then it is easy to retrieve this from the events when reloading the aggregate root from the event store. You just create the address property and an internal event handler to process the Customer Moved event. Just make sure you delete the snapshots first.
But if you do not store all the events that you publish, but instead store only a snapshot then I would not skip storing the new address information, because in the end the domain is responsible for the state, not the reporting side. In other words, you can rebuild the reporting side from the domain, but you cannot necessarily do the same in reverse. So if you don’t store the address information and you need to rebuild the reporting store then you cannot do this.
So my conclusion is that the information should be available on the domain side. And when using CQRS and Event Sourcing to store the events instead of the internal state of the domain then that makes it possible to skip having the information in the domain structure, else not.






Always nice to see people have similar ideas about some things. I’ve been asking myself the same question for a while now, and came to the same conclusion.
That is, until I started implementing snapshot events. If you want to use snapshot events to limit the number of historical events to load, your aggregate will need to fully maintain its internal state.
@Allard Buijze
You would only keep one snapshot per AR, so if you change the internal state representation of the AR then just delete the snapshot and let something regenerate it again. (I have a blog post coming about that as well). You would be doing this for each type of change.
@Mark Nijhof
)
I am eager to read your next post. I’ve enjoyed the previous ones, anyway (although your C# code samples use constructs that we don’t have in Java
My idea was that the “something” that generates the snapshot event would be the domain object itself. In order to do that, it should know what (for example) the last known address was.
@Allard Buijze
Yuo are correct the domain generates the snapshot and is the only one that knows the structure. But you can savely delete them as any-time, that just means that now all the events will be loaded again. Now you would probably have a daemon in the background generating snapshots, so hopefully when the AR is needed you don’t actually need to load all events. (I’ll discuss this in more details in the next CQRS post).
@Allard Buijze
Snapshotting doesn’t change the need to persist the state in question in this post. We’re simply discussing state that is irrelevant to business logic. You wouldn’t need it ever, so no need to store it in the snapshot. The only place its needed is in reporting, and as such, that’s the only place it lives.
@Aaron Jensen
Aaron, you caught me in a moment of “a snapshot captures full state” thoughts here. I probably didn’t get rid of all the “traditional” ways of thinking yet. You’ve got an absolutely valid point there. Thanks for that!
@Aaron Jensen
It looks like Udi is on the same line as you http://www.udidahan.com/2009/12/09/clarified-cqrs/comment-page-1/#comment-36874 saying that some information does not need to be in the domain model at all, independently of the way to build it. Meaning putting much more responsibilities on the reporting side then I imagined.
So your domain is basically in memory at all times. Meaning, none of your AR are disposed. You constantly add new ones in memory and save the state of those AR from time-to-time.
@Roy
I am not sure how you got that impression? The identity map determins how long an AR stays in memory, but that is not discussed in this post
I think the word “daemon” in the 3rd comment threw me off. To me, that means a background service. I was tring to make sense of why you would run a background service to commit a snapshot of an aggregate. I don’t think I understand the purpose of a snapshot. I was thinking that snapshots are only taken after a commit command is given by the client.