Using events to replicate a model across VMs / 'single image' model


I’m new to Axon, but let me first say thanks and kudos for what looks like a really useful and high-quality framework :slight_smile:

I am looking at an application in which (in a simplified view) there’s a server and some clients. Each client holds a distinct model, and the server holds a replicated copy of every client’s model, as a single model of the whole system. Or, looked at another way, the clients each have a small subset of the server’s model.

Events can spontaneously arise in the clients (the events represent things that have happened in the real world, so I don’t think they are commands, but maybe I’m misapplying the concepts). Each event needs to update the relevant entity in that clients, then be forwarded to the server to update the server’s copy of that client’s model.

It seems like I need the events to be dispatched and applied to entities in the server, based on the ID of the entity that raised the event in the client – in much the same way that commands are dispatched based on @TargetAggregateIdentifier. Does that sound sensible, or am I missing something? Would each entity have to register itself as a listener for “it’s own” events, or does that happen automatically anyway?

The server can comfortably hold its model entirely in memory, as a single object graph. There are many entity types within the graph that will cross-reference each other a lot. To keep the business logic and consistency-checking code in the entities clean and simple, I want to use real object references as much as possible (i.e. not refer to other entities by IDs).

Does this mean that the entire object model is a single aggregate, with some sort of ‘ModelRoot’ object as the single aggregate root? Entities within the model can still be looked up and found via Repository-like interfaces; commands/events will still be dispatched to entities based on target entity IDs. Changes can be persisted into event stores as they happen, and the entire model reconstructed from events when the server restarts.

Since the entire model is in memory at once, and fully connected to itself at all times, do I really need more than one aggregate root… or any at all?

Many thanks for your help,

Hi Richard,

interesting questions. I’ll try to answer them, but be aware that I have a very limited view on your domain.

  1. In short: one system’s event is another system’s command. If you want a system to update something because an event happened, you’re basically sending it a command. In the end, almost all systems use Commands that reflect a particular truth that has happened (or is about to happen) in the real world.

  2. Your assumption about the aggregate is correct. If you really need object references between objects, then they must be part of the same aggregate. I don’t know howmany events/command you expect to be processing, because a single-aggregate system doesn’t scale very well in either size or performance.



Hi Allard,

Thank you for your response.

  1. I wanted to keep the distinction between commands, which can fail or be denied (‘I want to start this app’), and events, which have already happened and cannot be refuted (‘This app just died’) – that happens to be a useful distinction in our domain.

I notice that in Axon neither commands nor events have any special interfaces/superclasses, so maybe with a bit of massaging and some liberal use of @TargetAggregateIdentifier I can just pump events through the command-dispatch mechanism? Alternatively I guess I could extend or customise the event-dispatch mechanism to work more like command-dispatch in certain cases.

I’m likely to use JGroups for both command and event distribution, so re-using, extending or emulating what you’ve already done with JGroups in the CommandBus area looks good.

  1. Cool, I’ll do a spike based on a single aggregate. All the central model code should be completely non-blocking and relatively quick, so I expect there to be lots of headroom around the throughput of model updates.

Thanks again - Axon is a great piece of work.

Hi Richard,

using a command doesn’t always mean a system can reject it. Let’s say that some commands are just a little more “forceful” than others. They don’t all start with “PleaseDo…”, after all.

In Axon, there is no distinction between commands and events, other than the type of Message they are wrapped in. So it’s technically possible to wrap an “event” in a CommandMessage and dispatch it via the command bus. Whether it’s functionally the best idea, I really cannot tell.