The silent metadata gap: command metadata doesn't propagate to events in Axon 5

We’re continuing to share learnings from our Axon Framework 5 migration (previous post: Our experience migrating from Axon Framework 4.12 to 5.0).

This week we hit a subtle bug that took some time to track down: command metadata was not propagating to events. Our aggregate history timeline suddenly showed events with no user attribution — just timestamps and event types.

The root cause: in Axon, commands and the events they produce have separate metadata envelopes. When you call EventAppender.append(), the new event starts with an empty metadata map.
The userId/userName we attached to commands via our AuthAwareCommandGateway stayed on the command — they never made it to the event store.

The fix was a single Spring bean:

@Bean
  public CorrelationDataProvider userMetadataCorrelationDataProvider() {
      return new SimpleCorrelationDataProvider("userId", "userName");
  }

Axon 5’s CorrelationDataProviderAutoConfiguration picks it up automatically — no manual Configurer calls needed.

What made this especially tricky:

  • No errors or exceptions. Events stored fine with empty metadata. Projections updated. Everything “worked.”
  • Tests didn’t catch it. Unit tests for command handlers verify event payloads, not infrastructure-level metadata propagation.
  • The command gateway was correct. Debugging command dispatch showed metadata present. The gap only becomes visible when you inspect stored events in Axon Server.

We wrote up the full deep dive with sequence diagrams and the internals of how CorrelationDataInterceptor works under the hood: The Silent Metadata Gap: Why Your Axon 5 Events Have No User Attribution

Has anyone else run into metadata propagation surprises during their Axon 5 migration? Curious if this caught others off guard too.

1 Like

Another lovely writedown, @petrmac. Super helpful that you’re providing input like this on the forum, so thanks a ton!

However, your predicament strikes me as a surprise. Although the configuration of interceptors and correlation data providers changed between AF4 and AF5, the nature of what data is propagated automatically from one message to another has always been the concern of the CorrelationDataProvider.

However, your pointers to me states that in AF4 this worked out of the box for you for (in this case) the userId. Perhaps a bit blunt a question, but are you absolutely certain that the previous application did not have a CorrelationDataProvider in your environment?

Nope, we did not have it. Pretty sure of that… I double checked the github history.

Alright…curious.
And, what about a custom set of interceptors that did this job?

Sorry to perhaps come across as pushy here (not my intention!). It’s just that the CorrelationDataProvider is not a new concept for Axon Framework 5. For custom correlation data like user information, we’d always have the user take on that job for themselves.

Now that I am typing this; are you users of the Reactor Extension in AF4? Maybe there’s something in there that did the correlation data population without consulting the user.

Yes, we had the extensions used in 4. Maybe some auto-configuration kicked in? Had to ditch the lib when migrated.
Plausible explanation…

Late reply here: my apologies :person_bowing:
But, I did a check just now into the [Reactor Extension](GitHub - AxonFramework/extension-reactor: Axon Framework extension for integration with Project Reactor, allowing an extended reactive API. · GitHub).
This component, indeed, copied over the entire context window into the Metadata of every Message. So, we got the culprit why this used to work for you, but did not when switching to AF5.

To be frank, I think AF should keep this as a CorrelationDataProvider concern. Hence, the work that’s currently underway to port the Reactor Extension to AF5, if anything, may have a dedicated CorrelationDataProviderfor the Reactor context.