Refactoring Aggregates

Hello Axon Team,

How would you recommend going about refactoring an Aggregate that has been released to Production. For example, if I had an aggregate with this structure:

Aggregate Root

  • Entity A
  • Entity B

We have a need to instead change the structure to:

Aggregate Root

  • Entity A
  • Entity B

where Entity B should now be a part of Entity A.

How should we do this while possibly keeping backward compatibility with stored events and how would we manage the impact of this in our DB (we’re using JPA repository for the Aggregate root and entitites)?

Thanks,
Mik

Hi Mik,

just to be sure, I assume you are storing your aggregates as JPA entities?
For the events, nothing changes from an Axon perspective. Events originate from an aggregate and don’t specify any details about the exact entity within that Aggregate that generated them. Obviously, there is likely some information in the events that allows you to trace the origin.

Normally, a refactoring of an Aggregate’s internal structure doesn’t change the output of the events. If that’s the case, you don’t need to do anything than the usual DB migration to change to the new format of storage.
Note that if your Aggregates are event sourced, you can just refactor your aggregate structure, and not bother about altering storage, at all.

Hope this helps.
Cheers,

Allard Buijze
CTO

E: allard.buijze@axoniq.io

T: +31 6 34 73 99 89

Hi,

sorry for hijacking this thread but I think the answer to my question may also contribute to the original question.

Allard, if I get your answer right, there is no persistent storage for Aggregate State at all if the Aggregates are event-sourced. Thus, the physical representation of the Aggregate in memory at runtime is always derived from the stream of events applied to this aggregate when starting up the application. This is indeed great for refactoring, since you only need to consider upcasting the Events (as they are the only persistent items), but what about performance of Aggregates that have a lot of events associated (latency until they catch up with the head of the event stream) and memory consumption of the Aggregates if there is a huge number of different Aggregate Instances (size of one Aggregate in Mem * number of Aggregate Instances)? Am I missing some persistent Snapshot of the Aggregate to avoid rebuilding state from scratch and having all State in memory? And if so, how do we migrate those Aggregate Snapshots? Is there also a kind of upcasting mechanism like for the events?

Thanks,
Jakob

PS.: I’m happy to move this to a new thread if you don’t think it fits here

Thank you Allard, yes I was referring to a JPA-backed aggregate. The DB migration makes a lot of sense.

In the case of event-sourced aggregates, what happens if we need to make changes to the logic in the EventSourcing handlers? How can you remain backward compatible with stored events?

Hi Jose,

In respect to event-sourced aggregate:

As the events are the source of truth, you can change the @EventSourcingHandler annotated functions however you see fit.
It’s those functions which are called to retrieve an Aggregate from the store.
Thus removing, adding or adjusting the internals of those functions will result in the Aggregate being retrieved differently.

This is purely a code change, luckily :slight_smile:

I hope this answers your question Jose!

Cheers,
Steven