We recently successfully completed migrating our CQRS/Event Sourcing backend from Axon Framework 4.12 to 5.0. The codebase has dozens of aggregates, multiple sagas, and hundreds of event handlers, so it wasn’t trivial.
We wrote up what we learned along the way — the biggest surprises were the scope of API changes (every package moved), replacing sagas with stateful event handlers backed by database persistence, and the underdocumented @EventTag requirement that silently breaks test fixtures.
@petrmac, I must applaud the effort you’ve put into this! We are planning extensive migration support, as we are fully aware of the sheer number of changes. Our first steps for this can be found here. But you did it nonetheless and wrote a blog post about it! I can’t stress enough how awesome I find it to read things like this, so thanks for sharing!
Thanks for the kind words, Steven! We initially implemented the service in version 4, but soon figured out that blocking code inside reactive chain is not a good idea. Now with reactive stack we can achieve excellent throughput with just 1 reasonably sized pod. Our stress tests show that with the reactive stack we can easily accomodate hundreds of concurrent users with just 3 gigs or RAM (roughly 10x)!
Will write more on the performance, once I have time.
Yep, fully migrated. We kept old sagas as deprecated for a while. They are deleted now and everything is now as stateful handler.
BTW, greetings from Devoxx Greece. If someone wants to meet, I will be around.
Did you have to use event scheduler instead of a deadline manager for stateful event handling, since the scope for deadlines’ are only sagas and aggregates?
We didn’t use EventScheduler in place of DeadlineManager — we replaced both. Time-based triggers became Spring @Scheduled jobs that query Postgres for what’s “due”, and multi-event coordination became ProcessStateService rows. When Axon 5.2’s saga module ships, we’ll likely keep this split: the deadline-attached-to-saga model is elegant, but for our two main use cases — batch-import coordination and trial lifecycles — DB-as-source-of-truth gives us better introspection and testability.