What to put into Events payload

1,749 views
Skip to first unread message

enrico sabbadin

unread,
Jan 21, 2015, 4:58:31 AM1/21/15
to ddd...@googlegroups.com
Hi, I've had a few experience on cqrs/Es pattern recently.

According to my experience it can make quite a lot of difference to subscribers implementation what you put as payload of an event.

Say you have a CustomerEmailAddressChanged Event ..
I can do it like this:

class CustomerEmailAddressChanged {
public guid idcustomer;
public string newemail;
};

or like this

class CustomerEmailAddressChanged{
public Customer customer;
public string newemail;
};

In the second case I put the whole AR in the payload , not only its Id

I think the first option is the one I've seen more frequently.

However .. suppose that a subscriber has a "weird" business rule stating : If the customer is from Italy it must have an email address ending with .IT
If it gets the first kind of event , it will have to load the customer AR to check this ..
if it has got the second kind of event , it will have already all the info required to run that business rule.

So my question is, what is the problem (but a bigger payload) if, as a general rule, one always put into each event payload, the full data of the AR that generated the event , instead of just its Id and the relevant data that strictly pertains to the event ?

thank you
enrico sasbbadin

Peter Hageus

unread,
Jan 21, 2015, 5:25:16 AM1/21/15
to ddd...@googlegroups.com

You dont have invariants/rules in the eventhandler. The entity/aggregate//whatever that generated the event is reponsible for this.

 

Also, you most certianly dont want to include a full aggregate in your event. How would this be persisted? (unless you’re doing the orm + domainevents pattern, I guess you could make it work on a technical level then. Doesn’t mean you should)

 

/Peter

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Greg Young

unread,
Jan 21, 2015, 5:26:34 AM1/21/15
to ddd...@googlegroups.com
You would check the logic you are talking about before generating the event not after.
--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Studying for the Turing test

@yreynhout

unread,
Jan 21, 2015, 5:40:25 AM1/21/15
to ddd...@googlegroups.com
"CRUD sourcing"

Greg Young

unread,
Jan 21, 2015, 5:42:04 AM1/21/15
to ddd...@googlegroups.com
Asynchronous crud sourcing.
--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexey Raga

unread,
Jan 21, 2015, 6:00:13 AM1/21/15
to ddd...@googlegroups.com
My suggestions would be:
- Don't include entities in your events. Entities are about behaviour, not about transferring data. No need to expose them to the outside world. 
- Neither don't create events that replicates your entities data. You are not doing CRUD this time.
- Don't put everything in your events just in case if some day some subscriber may find it useful. It just complicates things a lot.
- Instead include into an event only information that is meaningful for that event. In your example, a customer id is relevant for identification and a new email is relevant as data. But all the other things that Customer entity may have (I don't know, maybe active/inactive, or maybe a phone number) is totally irrelevant to the fact represented by the event. 

There can be the whole can of worms be opened by starting "skinny events vs. fat events", but I'd recommend you to always start with skinny and then add more data only when necessary (with double and triple thinking about it).
I'd also recommend you to design your events without knowing too much (ideally nothing) about who and why would consume them. Look at them as at facts that you want to expose about what you've done.

Cheers,
Alexey.

enrico sabbadin

unread,
Jan 21, 2015, 6:18:48 AM1/21/15
to ddd...@googlegroups.com
I quite don't get the fact that putting the whole AR in the event payload is "CRUD sourcing" .. I mean , for sure the whole AR payload is unnecessary when reconstructing the AR,
Im my example, putting the whole AR in the payload is done to make subscribers life easier and quicker (to avoid they have to reload the AR ).

My post was actually inspired by the following quote I extracted from here : "CQRS Journey" :  https://msdn.microsoft.com/en-us/library/jj554200.aspx

"Our assumption that events should only contain information about the change in the aggregate or the bounded context proved to be unhelpful; events can contain additional information that is useful to one or more subscribers and helps to reduce the amount of work that a subscriber must perform."

"inspired" by that, I asked myself what would have been wrong putting the whole AR in any case, instead of deciding to add additional info on a case by case basis.

I know that ideally publisher should know as less as possible about its subscribers .. but that's a guideline that must evaluated together with other "tensions" . .such as performances.

Greg Young

unread,
Jan 21, 2015, 6:28:23 AM1/21/15
to ddd...@googlegroups.com
Sometimes to learn lessons you have to build the thing in question.
Implement the way you are discussing then try refactoring your domain
object to rename something or add a value object.

Cheers,

Greg

Peter Hageus

unread,
Jan 21, 2015, 7:52:12 AM1/21/15
to ddd...@googlegroups.com

If your AR is Customer  { Id, Email, Name }, then by all means, put it in an event (there are several other reason not to do this, but based purely on the content, fine). The term crudsourcing seems appriate for this.

 

But if it doesn’t look like that, and is more about behaviour than storing data, how are you going to use it in your eventhandler? To execute domainlogic?

 

/Peter

--

Greg Young

unread,
Jan 21, 2015, 7:54:25 AM1/21/15
to ddd...@googlegroups.com

Dont put entities on the wire.

Peter Hageus

unread,
Jan 21, 2015, 8:19:22 AM1/21/15
to ddd...@googlegroups.com

Like I wrote, the are several reasons not to. But if you’re doing crud (and I don’t think this is eventsourced or have any behaviour, or the question wouldn’t have come up), and use loose schema, there’s a footgun and a pair of scissors at you’re disposal that might be fun to play around with ;-)

 

/Peter

enrico sabbadin

unread,
Jan 21, 2015, 8:44:28 AM1/21/15
to ddd...@googlegroups.com
yes, in my example the handler would use the "extra info" for business-rules/domain logic .. it would avoid "AR lookup by id" if it had the whole AR (the idea is that is the AR itlself issuing the event so it is already fully constructed from the EStore)  

something like :

var x= new CustomerEmailAddressChanged{
customer = this,
newemail = this.email
};
or even better
var x= new CustomerEmailAddressChanged{
id = this.id,
newemail = this.email,
TheFatPart = this
};

btw : the handler could be a projection handler as well .. even in this case having the AR available it might let the handler avoid some lookups (depends on its implementation of course).

to recap, options are :
a) put only info that are strictly related to the semanthich of the event and are required to reconstrcut the AR (cons: handlers will often need to do AR by id look ups, so performance may suffer)
b) put extra info required by handlers when it would cost them too much to lookup at such info (this introduce some copuling between publisher and subcribers)
c) put the whole AR in the event payload in the "TheFatPart" field (cons: event payload grows .. i'm mostly concerned about the extra cost in moving a lot of unusefull data on the wire when reifdratating the AR) ..maybe an overload of the method ReadEventsFromStore(guid Id, bool loadTheFatPart = true/false) would help :)

Peter Hageus

unread,
Jan 21, 2015, 9:12:40 AM1/21/15
to ddd...@googlegroups.com

I’m afraid your missing the point:

 

If you really have a behavioural domainmodel, you wouldn’t have much use for an AR in your eventhandler. If you don’t, there are more suitable patterns for dealing with your data (crud, etc).

 

(there’s an old thread in this group about storing crud-data as events to keep operational complexity down (which I think is a valid concern), I suggest you read it)

enrico sabbadin

unread,
Jan 21, 2015, 10:12:27 AM1/21/15
to ddd...@googlegroups.com
Peter, I'm afraind you are missing mine,
maybe it's not legal ?! to have an event handler that directly loads/Create an AR and send the event to it.. I'm not sure about , but i saw some samples doing that.

Anyway, let's go then to a more CQRS classic flow: event handler create a command and send it -> command handler load an AR and send the command to the AR .. finally this AR needs to do its business logic
To do this it needs some info that the event/command payload don't have (may the handler is part of a saga ) .. I hope now it sounds more classic CQRS.

I hope I managed to clarify the point of my question (eventpayload). if not .. thank you anyway .. I got some interesting considerations anyway
best regards

Greg Young

unread,
Jan 21, 2015, 10:14:51 AM1/21/15
to ddd...@googlegroups.com

This is very confused. Id spend some more time reading etc and implementing in test projects before moving forward on a work project

enrico sabbadin

unread,
Jan 21, 2015, 10:39:54 AM1/21/15
to ddd...@googlegroups.com
maybe :) .. for sure I still have to get your slang (UL) to communicate efficiently in this forum :)

Peter Hageus

unread,
Jan 21, 2015, 10:45:13 AM1/21/15
to ddd...@googlegroups.com

Have a look at Greg’s (?) SimpleCQRS. It’s a lot easier to get a grasp of, than the P&P Journey (wich I found rather confusing and very focused on infrastructure)

Kijana Woodard

unread,
Jan 21, 2015, 11:04:04 AM1/21/15
to ddd...@googlegroups.com
@enrico - loading an Aggregate Root in an event handler just doesn't make sense. I don't mean technically. You can move bits around any way you like. But the purpose of an Aggregate Root is to encapsulate data and behavior. 

It's hard for me to find the right words to express the disconnect. It would be like talking about feeding grapes to a mountain so it can survive a journey to Mars.

Most of the time when I have a desire to put a lot of data on an event, I find that 
1) my boundaries are off
2) i'm doing crud, so be it
3)  haven't properly captured previous events in the consuming context.

For instance, if you had previously published "CustomerCreated", why would you need to add all that data in this subsequent event?

In the particular case cited, I agree with others that you should check those kinds of invariants / business rules before the event is created. There *might* be a reason to do it later, but that would be a somewhat advanced technique involving compensating events that seems unlikely.

Look at it from this perspective : why would two actors in a system be responsible for *writing* the same data? They would always contend with each other to determine who is correct. How could any reader of the data be certain that the disputes were settled?

Brian Mavity

unread,
Jan 21, 2015, 11:07:36 AM1/21/15
to ddd...@googlegroups.com
It has nothing to do with the language, it has to do with what seems to be a fundamental misunderstanding of the concepts on your part. What are you trying to accomplish here?

The flow starts with:
  • User -> Command -> Command Handler -> AR1 -> Event
and then you are saying you want to do:
  • Event -> Event Handler -> Command -> Command Handler -> AR2
You say that to process the last Command, you either need all the data from AR1 on the Event or you need to load AR1 in the Command Handler. There are a few things to be said about this:
  • AR1 is for behavior/writing, not reading. You would read from a Read Model if you needed additional data.
  • Read Models are created from Events
  • AR generally do not keep all their state, only the state needed to make decisions in the future.
  • The Event data is used to create the Command here, you do not send an Event to an AR.
  • If AR2 needs all of AR1 data, you likely have a modelling issue.
Like people have been saying, go back and do some more reading and create some examples.



On Wed, Jan 21, 2015 at 9:39 AM, enrico sabbadin <sabba...@gmail.com> wrote:

enrico sabbadin

unread,
Jan 21, 2015, 11:54:57 AM1/21/15
to ddd...@googlegroups.com


@enrico - loading an Aggregate Root in an event handler just doesn't make sense. I don't mean technically. You can move bits around any way you like. But the purpose of an Aggregate Root is to encapsulate data and behavior. 

I know .. it was just a quick way to get to the point : it should have been : command A arrive from UI , command handler A load AR A and pass the command info to it .. AR A publish event A, an event handler receives event A : in its implementation creates command B and send it .. command handler B receives this command ; it creates AR B and pass to it the command B information .. within the AR B method the job is done... but since Event A is a slim event , it missis some info (it has only an idref , so it will have to do a look up) .. my question was pros anc cons of making event A a fat one, h all the AR A in its payload ) .. that's it

It's hard for me to find the right words to express the disconnect. It would be like talking about feeding grapes to a mountain so it can survive a journey to Mars.

Most of the time when I have a desire to put a lot of data on an event, I find that 
1) my boundaries are off
2) i'm doing crud, so be it
3)  haven't properly captured previous events in the consuming context.

For instance, if you had previously published "CustomerCreated", why would you need to add all that data in this subsequent event?

because , while the publising AR have both event, other subscribers might be happy to have all the data as well (if not they need to lookup) .. It woud take too long to explain this situation in a real scenario I met , but , trust me it was a real one :)

Greg Young

unread,
Jan 21, 2015, 11:57:05 AM1/21/15
to ddd...@googlegroups.com
"because , while the publising AR have both event, other subscribers
might be happy to have all the data as well (if not they need to
lookup) .. It woud take too long to explain this situation in a real
scenario I met , but , trust me it was a real one :)"

Why are subscribers looking up an AR? This sounds horribly broken

enrico sabbadin

unread,
Jan 21, 2015, 12:09:02 PM1/21/15
to ddd...@googlegroups.com
Commnents inline

On Wednesday, January 21, 2015 at 5:07:36 PM UTC+1, Brian Mavity wrote:
It has nothing to do with the language, it has to do with what seems to be a fundamental misunderstanding of the concepts on your part. What are you trying to accomplish here?

The flow starts with:
  • User -> Command -> Command Handler -> AR1 -> Event
and then you are saying you want to do:
  • Event -> Event Handler -> Command -> Command Handler -> AR2
You say that to process the last Command, you either need all the data from AR1 on the Event or you need to load AR1 in the Command Handler. There are a few things to be said about this:
  • AR1 is for behavior/writing, not reading. You would read from a Read Model if you needed additional data.
In many posts I read around here, mostly said not to use the read model on the write model , if you need to read on the write side use the Ar itself
  • Read Models are created from Events
  • AR generally do not keep all their state, only the state needed to make decisions in the future.
  • The Event data is used to create the Command here, you do not send an Event to an AR.
yes I known that was to cut a long story short 
  • If AR2 needs all of AR1 data, you likely have a modelling issue.
again : my question was pros anc cons (also performance problem ) about deciding to take a draconian approach : Always put all the AR as "extended data" in the event
 
Like people have been saying, go back and do some more reading and create some examples.


Again , Thank u 2 for the suggestion .. b.t.w. : One of the take aways I can get from my first readings on this forum , and not only, is that there are hardly 2 ppl that agree on most subjects :)

and I suggest you guys to end your posts with IMHO  more frequently ;

my 2 cents

Kijana Woodard

unread,
Jan 21, 2015, 12:11:58 PM1/21/15
to ddd...@googlegroups.com
"because , while the publising AR have both event, other subscribers might be happy to have all the data as well (if not they need to lookup) .. It woud take too long to explain this situation in a real scenario I met , but , trust me it was a real one :)"

Stipulation: it could be that the term "AR" is tripping us up. An "AR" most likely does *not* have the state that some other context would need. Why would the "AR" keep something like customer name around? What business rule would use this information? However, lots of other things might need the "Customer Name" [a greeting in an email for instance]. In any event, no other context should be loading up an "AR" to do it's work. I think from what you wrote, you just mean "fat event" meaning, putting "lots of data" on the event.

Back to choices.

1) Put the name [or email or whatever] on every event.

2) Subscribers listen for the relevant events they will need and store the data themselves. Ex: When sending an email confirmation, greet the user with their full name. Impl: listen to CustomerCreated and store name and email. listen to email changed and send email to previous and new email. listen to CustomerNameChanged and ....

3) When it's time to send an email, ask a relevant component for the Customer's name. That component could look it up in a database, use a rest api, cache it locally from events, whatever. 

The "AR" isn't involved here.

The downside to #1 is it makes testing and change very hard and, frankly, tedious. The upside is that it's easier for any subscriber to have context.

#2 is simpler, but subscribers to maintain their own state. There is more risk when changing events.

#3 is the most loosely coupled and flexible with the downside that you have to develop and deploy more components. There are more moving parts at run time.

I'm sure there are many more patterns.

Hope that helps.

Kyle Cordes

unread,
Jan 21, 2015, 12:17:45 PM1/21/15
to ddd...@googlegroups.com
On Wednesday, January 21, 2015 at 10:57 AM, Greg Young wrote:
> "because , while the publising AR have both event, other subscribers
> might be happy to have all the data as well (if not they need to
> lookup) .. It woud take too long to explain this situation in a real
> scenario I met , but , trust me it was a real one :)"
>
> Why are subscribers looking up an AR? This sounds horribly broken
Curiously, this perhaps relates to the discussion on the other thread. Obviously a subscriber should not be looking up a AR period in fact, if the subscriber is a projection and it tries to access that, I suggest a kill -9 of the process is in order. :-)

The connection is: A projection tends to build up a representation of things that resemble entities and or aggregates in the domain. It further tends to build those up connected to each other, making certain kinds of processing possible. This kind of logic can easily end up duplicated from one projection to another. A fresh adopter of CQRS might attempt to solve that problem by looking up an AR via the event store (!), but that does not mean they are foolish, that only means they are dodging duplication - a worthy goal. Hence the connection to my question, how to avoid code duplication among projections?


--
Kyle Cordes

http://kylecordes.com


Greg Young

unread,
Jan 21, 2015, 12:20:43 PM1/21/15
to ddd...@googlegroups.com
"again : my question was pros anc cons (also performance problem )
about deciding to take a draconian approach : Always put all the AR as
"extended data" in the event"

Read my earlier post about trying it.

The performance problems have nothing to do with it a 400 byte vs 2k
event is not a big deal. The coupling is a huge problem.

But you seem very set on doing it. All I can say is try it, as I said
previously. You will understand in a few months why its normally a
really bad idea.

Greg

Kijana Woodard

unread,
Jan 21, 2015, 1:11:54 PM1/21/15
to ddd...@googlegroups.com
"In many posts I read around here, mostly said not to use the read model on the write model , if you need to read on the write side use the Ar itself"

I think this applies to an AR using a read model to make decisions vs to build a command. 
There's a subtle difference.

There's also a prohibition against using a read model generated from "an AR's own" events. Why do that when you can keep the state you need to make decisions.

That said. IMHO, there is no strict "write side" and "read side". There is separation of the two, but within a context.

Take the case of a Product Management Context and a Shopping Context. Product Management publishes ProductReadyForSale { productId }. 

You could also put name, price, etc in the event. 
You could have ProductManagement deploy components for subscribers to query the extra data they need for their work.

Trade offs.

Personally, I lean toward the latter [thin events] implemented via Consumer Driven Contracts[1]. It lets me be quite certain what consumers are actually dependent upon and what needs to be considered during change management. It also allows the Service that owns the data to completely control the implementation of providing it's data.

The downside is that it's more work upfront.

While I lean toward thin events, it's as a guide post. I break that "rule" with abandon for a variety of reasons.

Also, consider that most of the time what you need here is not querying another context's read model for an AR, but rather you're building a composite UI. An email is a good example of that. Generally email == screen/view == report == composite view model. 

Be cognizant of autonomy. Needing to *query* another context in order to make a decision in this context signals that boundaries are off or undesirable coupling is occurring. 

I will say that I bristle at "you need to go read up", especially with no specific links. That response is getting ever more popular around the web as a quaint way to say "sod off". 

However, the suggestion of writing some code while keeping this thread in mind is quite valuable. Nothing teaches like experience. It's nice to be able to say, "oh I see what they meant", even if you conclude they were wrong.

enrico sabbadin

unread,
Jan 21, 2015, 1:13:10 PM1/21/15
to ddd...@googlegroups.com
"AR" most likely does *not* have the state that some other context would need. Why would the "AR" keep something like customer name around"


very good point .. this answer the queastion why I shouldn't put the AR in the event payload in all cases
thank you

Brian Mavity

unread,
Jan 21, 2015, 1:16:37 PM1/21/15
to ddd...@googlegroups.com
I got distracted toward the end and came off a bitch harsh. Apologies. :)

Greg Young

unread,
Jan 21, 2015, 1:17:44 PM1/21/15
to ddd...@googlegroups.com
freudian slip?

Kijana Woodard

unread,
Jan 21, 2015, 1:20:16 PM1/21/15
to ddd...@googlegroups.com
tyvm for the apology [though not aimed at me per se].
my twitter feed of late has caused me to rethink my own belligerent approach to these discussions. 

twitter is vile. ;-]

enrico sabbadin

unread,
Jan 21, 2015, 1:20:23 PM1/21/15
to ddd...@googlegroups.com
"Why are subscribers looking up an AR? This sounds horribly broken "

Greg

if I got it well, it was discussed using AR look up against projectjons in a command handler .. and the majority opted for reading from the AR  

Brian Mavity

unread,
Jan 21, 2015, 1:21:29 PM1/21/15
to ddd...@googlegroups.com
Hah whoops.

Greg Young

unread,
Jan 21, 2015, 1:21:48 PM1/21/15
to ddd...@googlegroups.com
WTF does this have to do with putting an AR serialized in an event so
an EVENT HANDLER had it?

Kijana Woodard

unread,
Jan 21, 2015, 1:24:18 PM1/21/15
to ddd...@googlegroups.com
I only skimmed the thread, but I'd lean toward @yreynhout's "missing model" assertion in that case. YMMV.

enrico sabbadin

unread,
Jan 21, 2015, 1:32:35 PM1/21/15
to ddd...@googlegroups.com
greg, the link I provided has to do with your statement :  "Why are subscribers looking up an AR? This sounds horribly broken "

Greg Young

unread,
Jan 21, 2015, 1:47:42 PM1/21/15
to ddd...@googlegroups.com
yes and you still I don't think understand the thread if the solution
is to "include snapshot state of aggregate inside the event"

Alexey Raga

unread,
Jan 21, 2015, 10:12:15 PM1/21/15
to ddd...@googlegroups.com
>>Im my example, putting the whole AR in the payload is done to make subscribers life easier and quicker (to avoid they have to reload the AR ).

What if your subscribers live in different BC? What if somewhere in Payments BC or, say, in SmapList BC I want to subscribe to your CustomerEmailChanged event? Should I now understand the internals of your AR? Why would I do that? What if you change it then? Should you find and change all the subscribers as well?
Also, each BC has its own representation of a Customer, providing different behaviour which is relevant for that very BC.
The Customer AR in Marketing BC would deal with emails, names, active/inactive maybe, etc. The Customer object in Payments BC would deal with payment methods, preferred currencies, etc. Why there should be a reason for them to expose their Customer representations to each other?
By doing that you would only introduce coupling which leads to inability to easily maintain / reason about your code and logic. You are working against that "B" in BC :)

>>My post was actually inspired by the following quote I extracted from here : "CQRS Journey" :  https://msdn.microsoft.com/en-us/library/jj554200.aspx
Don't read that stuff. It is awful. Really, I followed that "journey" and then it was like "Mom, how do I unlearn things?"
I believe many "big names" on that "journey" were pissed off by how it went: Udi was angry about it, I remember Greg making fun of it, etc.

I'd rather recommend you to watch Greg Young's 6 hours video (just google it like that) to learn DDD/ES basics. This is VERY good stuff and you won't regret watching it. It also addresses and explains your concerns.

Cheers,
Alexey.

enrico sabbadin

unread,
Jan 22, 2015, 2:54:17 AM1/22/15
to ddd...@googlegroups.com
Thank Alexy, you brought up another good reason why I shouldn't do it.
thank you
Reply all
Reply to author
Forward
0 new messages