Date Format Incompatibility in Event Sourcing - Cannot Deserialize ISO 8601 Date After Format Change

Hi Axon community,

Sorry for my poor English as it’s not my native language. I’m facing a date format compatibility issue with event sourcing in production and would appreciate your guidance.

Background

Initially, our system didn’t specify a date format for java.util.Date fields, and Axon/Jackson was serializing dates in ISO 8601 format like:

“2026-03-30T00:00:00.000+00:00”

Later, we updated our code to use a specific date format by adding @JsonFormat annotation:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date deliveryDate;

The Problem
After deploying this change to production, when Axon tries to reconstruct aggregates from historical events, we get the following error:

org.axonframework.commandhandling.CommandExecutionException: 
Error handling event of type [class com.smartchain.event.tms.TmsBatchCreateWaybillEvent] in aggregate

Caused by: Error while deserializing payload of message f5e622e8-5a1c-4ba5-bc18-2477169a3a78

Caused by: Cannot deserialize value of type `java.util.Date` from String "2026-03-30T00:00:00.000+00:00": 
expected format "yyyy-MM-dd HH:mm:ss"

The Issue
The problem is that:

  • Historical events in Axon Server contain dates in ISO 8601 format
  • New code expects dates in yyyy-MM-dd HH:mm:ss format
  • When Axon reconstructs aggregates, it fails to deserialize old events

My Question

How can I handle this date format incompatibility in Axon Framework? Specifically:

  1. Is there a way to support multiple date formats during deserialization to maintain backward compatibility?
  2. Should I use a custom deserializer that can handle both formats?
  3. What’s the best practice for handling date format changes in event-sourced systems?

What I’ve Tried
I’ve created a custom FlexibleDateDeserializer that supports multiple formats, but I’m not sure if this is the recommended approach for Axon event sourcing.
Any guidance or best practices would be greatly appreciated!
Thanks in advance.

Hi @Just_Right ,

The keyword for this are the upcasters. They are the components that are responsible to convert the messages (especially event messages) from one format to the other. Whenever your events evolve in an incompatible way (or as in this case the serialization format changes) you implement such an upcaster to compensate this. The upcaster chain is applied before each deserialization and can thus transform the old date format into the new one.

Best regards

Nils