Should eventType be globally unique?

Hello, I love the new discussion forum!

Sorry if this is a repeat, but this is a question I’ve scoured the mailing list and google for, but have not had luck finding a good answer.

Given that I’m using one event stream per aggregate, is it important to use names for my eventType that are globally unique, even across different aggregates?

As a small contrived example, if my system has MortgageApplication and CarLoanApplication aggregates, it would make sense to the business owners if BOTH aggregate streams had a ContactAddressAdded event. (Also assume the contents of the event data are also identical: street, city, etc ).

One the one hand, this might make it difficult if I had projections running on the $all stream, listening for ContactAddressAdded - I might not be able to easily distinguish what product the contact address is for?

However, making the names globally unique can make the event stream feel a bit more ham-fisted. For example, my mortgage log of:

[ ApplicationSubmitted, ContactAddressAdded ]


[ MortgageApplicationSubmitted, MortgageApplicationContactAddressAdded ]

…scaling that out into the full scope of the application, it seems the global names make things awkward. It also feels like the prefix means I need to be aware of ALL possible bounded contexts at the same time - and possibly breaks the idea that the same prefix might mean something different to different contexts.

It also seems like it could lead to rampant duplication of essentially the same logic, when my application offers 20 different types of financial products, all having the same concept of a “contact address”.

Are there any suggestions for best practice? Am I overthinking this? Thanks so much for your time!

For your example ContactAddressAdded, the events might be a perfect fit for each Aggregate, but my worry would be if a requirement came along to modify the ContactAddress when added to a Mortage for example. That change could potentially impact the CarLoanApplication.

I know what you are saying about having mutlple event handler for ContactAddressAdded per aggregate, but for me anyway, it’s probably worth that and having clean boundaries on the events.
Even for things like having a proeprty called MortgageId and CarLoanApplicationId in the events to related back to the aggregate, rather than a generic AggregateId.

If a consumer pick up ContactAddressAdded looking like this:

{ Address : “some address”, AggregateId : “some id”> }

Was this for a Mortage or a Car loan?

Thanks @steven.blair! That was very helpful, and reassuring to my better senses. I’m sure I can overcome some of that duplication with composition and the like… having a more concrete domain model does seem to be the wisest way forward.

1 Like

It might be just a sample but I don’t think a field like AggregateId is a good naming strategy. I’d say it should be something ContactId.

We usually add something EventSource field to the metadata and set the aggregate type there, so we know where the event comes from. The event type uniqueness is only relevant for systems that use $et projections and expect events of a certain type to come from a single aggregate and therefore might get confused when they get something unexpected. By adding something that you can use to distinguish those events, it will not solve the issue of subscriptions to receive those events (traffic) but events will be filtered out on the client side and it will work ok.

Thank you @alexey.zimarev! That approach really appeals to me, since my events can be more of a natural fit for each aggregate.

Related question: So far, I’ve used a similar approach with the aggregate id. (Using my original example above) Rather than every event in the stream having an applicationId field in the event data, I typically have been using the streamId of the event to get the aggregate’s ID, since I’m using stream-per-aggregate. The aggregate’s id isn’t really part of the business language in many cases. ( Is that recommended? )