Eventstream version with a split stream


I have a UserEvents stream that I split into UserEvents-[EntityId] categories. Now when I want to Load an User aggregate, I load it from the stream UserEvents-5. When I have 3 events in the UserEvents-5 stream the stream version is of course 5 but the version of the stream that I append to (UserEvents) can be a lot higher, as there are more users. So right now I get the event version directly from the event and not from the stream. But of course, when I try to write Back and someone changed the UserEvents-4 stream, the versionof the stream also changes even though the user 5 was never touched. So far this is ok for me, as there are very little changes in the stream, to have a concurrency problem between loading and saving the aggregate. But This might get ugly pretty fast. So is there a way I can get those two versions in relation to each other? Or should I take another way of handling those concurrency problems?



The general advice is to have a dedicated event stream per aggregate. That applies to writing events - not just a partitioned stream for reading.

Do you have a particular need to write all of your user events to a single stream?

Welp, this is embarrasingly obvious now :wink:

I was writing the events to a User Stream as I saw that in a tutorial. Of course I could do that without emit and just write User1 to User-1 and so on. But would that not complicate subscribing to those events from another service? Or would I merge those user events into a single event stream again with the categories? Like for example when I want to send a Mail on every UserCreatedEvent, I would subscribe to the UserEvent stream and send the mails accordingly.

Do you mean Aggregate as class or instance? To me it is the class and therefore I have a eventstream with all events for the multiple instances.


Per instance. I only used the word aggregate because you already had, but didn’t pick up on the fact that you were using it to imply class. Sorry for any confusion.

You are right that you can then take advantage of your instance streams being in a category. You can subscribe to the category stream to get the events for all instances in that category.

Perhaps you will have a projection that materialises your instance states from their individual streams “by_category”? It will likely be using partitioning “foreachStream”. Again, you can subscribe to the individual emitted partition streams or to the projection’s result stream which contains all instances.

Maybe I define some words here how I understand them:

Aggregate: A boundary of some entities

Entity: Just a “class”

Instance: a concrete Instance of an entity or an aggregate

Ok, I just tried to figure out if one stream per instance is a good idea or not. I am not completely sold yet. I have some troubles with the idea that I have to know wich event belongs to wich stream. I would much rather just append to one Stream of say a UserAggregate and read from this stream when I want to load a User Instance. But then the events for User1 and User2 are in the same stream. I just pictured a scenario where your Aggregate is consisting of multiple Entities and you have an Entity that is shared by two User Instances. Maybe an Town Entity (dont have a better idea right now). Then you change the name of the Town so you write a “TownNameChanged” event but now I do not know where I put this event. I must know wich user lives in the same town and have to write the event to their streams. Otherwise my projection will be wrong when I run them and collect all events for a User. Or I would have to write it to a Town Stream and linkTo it to the user streams with another projection. I much rather would like to put the “TownNameChanged” event in the main stream and read it once with a projection when i recreate the User. It just seams much more straight forward to me like this. I tried it with a concatenate Projection that puts all events from the streams for each instance in and this works but Appending just gets way more complicated in this scenario. At least how I experienced it.

Or did I get you wrong somewhere?

Each entity (Town) should have a unique, immutable ID (123) - it is recommended that you append events associated to this entity to a single stream (TownEvents-123). Your entity might have various properties (Name) that can be changed (TownNameChanged). You can use the EventStore by_category built in projection to give you a stream of events for all towns ($ce-TownEvents). You can also use a custom/user projection (written in JavaScript) to give you a web endpoint (on the EventStore master node) that could for example give you a JSON list of all towns (without having to read all events in $ce-TownEvents) or even a JSON map of TownId -> TownName so you can use that to lookup which town to add you citizen to (if you only know the town name when you want to add the citizen).

Hope this helps

Ok I found some time to revisit the project and I still do not get a
few things.
First of all my entities all have an ID and for now I put User and
City in separate streams and appended their ID so I can make
projections by category with the ID. But this leaves still a problem
that I do not seam to be able to solve. My aggregate is the User and
the Users has a Town as a field. Lets say when I create a City, I do
not need a User, but there should be a "UserMovedToCity" Event that
consists of a user Id and a City ID. I would put this is the user
stream so when I load the User, I will have a json object like

UserId: 14
UserName: "Peter"
   CityId: 123
   CityName: null

But this is not a valid state of my aggregate, as CityName should
always be set. But a "CityCreated" event only would have a CityId and
a CityName. So what I would have to do is load the User in its non
valid state and apply the corresponding City onto him. But those are
two requests and just does not seem right at all.

I was thinking of making a projection with linkTo from the CityStream
to the user Stream, but this is not very good aswell. I also was
thinking of putting the city events in the user stream, as they are
one aggregate, but then I would have the problem to decide where to
put a "CityCreated" event or a "CityNameChanged" event would have to
be applied to all user aggregates that are living in this city. Those
are all terrible ideas but I can not seam to figure out how I would
implement such a parent child relationship.

Maybe the example is really bad, as in real live I would model them as
two separate aggregates and would only have a CityId as a Property in
the User Aggregate. But I am pretty sure that there will be a day
where I would really have to implement a Parent Child relationship
within an aggregate and then I would have to have an Idea how to
handle this.

Thanks for the insides so far, It was very helpfull!