Search code examples
architecturedomain-driven-designcqrsevent-sourcingaggregateroot

Event Sourcing Re-hydration every Command?


I have an event sourced system that is complemented with CQRS patterns. Every command that is issued to the server will re-hydrate my aggregate (a newly initialized aggregate) to the current state with an event stream, assuming the command is valid.

My question is - Why should I re-hydrate my aggregate state every command? Why can't I just keep an aggregate instance per aggregate Id and not worry about re-hydrating every command? In this scenario, I would only re-hydrate events while spinning up the server.

Is there anything wrong with doing this? It would still preserve history of state because events continue to be persisted.

Thanks!

edit: I am snapshotting my aggregate state every n events so I shouldn't have to re-hydrate more than n events every re-hydration. Additionally, I am caching the aggregate state every time a new snapshot is saved to save a request for the state. I am more wondering why even re-hydrate at all if I could just keep a running aggregate instance in memory (per aggregateId).


Solution

  • I agree with @voiceofunreason for almost all cases (speaking from personal experience) that storing\caching the "current" aggregate state is perfectly fine. However, you should be aware that there are some things that you may be missing by doing so:

    1. You are not exercising rehydrating your aggregate. This may hide versioning issues long enough to become a big problem. Think of this as being similar with taking backups of your db, but never testing restore.
    2. By storing a cache you're missing the opportunity to use late-fire events. For example you could have an event like "New pricing applies after November". You would store this event once you have it, but it affects state (pricing) only after a certain date. Granted, this is a specific (and admittedly not particularly common) situation, but it is something you will be losing.
    3. You will not be able to have (bi-)temporal queries like "What did I know about X aggregate at that point in time".

    Point 1 is more important than the others but there are ways around this witout actually rehydrating every time. It is just that rehydrating is a good option in many cases.

    Using snapshots alongside events, and rehydrating using snapshots + newer events addresses these problems because:

    1. Reconsitution is exersised up until you snapshot
    2. When you have a "late-fire-event", since snapshots are stored side-by-side with events, it's easy to stop snapshotting until the late-fire event applies, after which you are fine to snapshot.
    3. You can bypass the snapshots for temporal queries.