← Ingestions

Ingestion 43cc404e reextracted

Format
transcript
Kind
talk
External ID
Event Sourcing Anti Patterns and Failures - Nathan Ladd - wroc_love.rb 2018.txt
Content hash
f7c4f6f923b2
Source at
2018-03-16 09:00
Manual extractions are temporarily disabled.

Extractions (2)

Status Model Tokens (in/out) Duration Cost Nodes/edges Read set (nodes/edges) Time
completed claude-opus-4-7
226,664 / 15,489
96,419 cached · 14,377 write
244.2s - 33 / 51 97 / 36 2026-04-17 17:51
completed claude-opus-4-7
327,095 / 5,786
151,817 cached · 14,377 write
112.8s - 0 / 0 85 / 8 2026-04-17 16:18

Content

hello everyone how's everyone doing


today good


awesome so I mean I'm here to talk to


you about everything that you're doing


wrong with event sourcing which is one


of life's greatest pleasures


I'm Nathan Ladd you can find me at real


ntl on Twitter and as mentioned I am a


co principal of the event ID project


it's a toolkit for building event


sourcing projects using event sourcing


as well as autonomous services so before


I begin I noticed on the schedule I am


the first speaker presenting about event


sourcing so hopefully I can give us a


brief review of what event sourcing is


and save the the remainder of the talks


a little bit of time if I do a bad job


with my review they'll have to of course


explain it again and then explain why I


was wrong so hopefully I help them out


so before I talk about event sourcing I


want to just go back to basic web


application stuff and that's web forms


and I want to call web forms by a more


general generic name which is commands


or command messages so this is a typical


web form and it's your browser submits


it to your app server your web server


and and your your web server handles


that form command so I'm gonna call it a


command message because when we're in


the context of microservices and when


we're in the context of a rails app for


instance we're all just talking about


handling commands and command messages


and when you have a web controller like


an MVC controller and your web app you


you can also think of that as being a


command Handler and the important thing


there is that our handlers are the entry


point of our code so around around that


handler you have framework and machinery


and plumbing but but the handlers are


where your code is first executed so I


want to talk about to do to explain a


eventsource thing I want to talk about


how your typical MVC plus ORM web


framework handles form submission so we


have in a deposit funds into an account


command message and I want to show kind


of how its it's handled by your web MVC


framework so first thing that happens is


usually in your controller you retrieve


your model and then you


figure out what changes to make to the


models for instance increase the account


balance might be a change and then you


apply those changes to models usually by


some attributes API like an active


record and then you validate the new


model State and based on that you save


the model state if the the new state is


valid and then callbacks get triggered


and of course callbacks when they're


triggered they can cause other models to


update and you might have callbacks in


and cue background jobs which sends you


right back to where you start and this


is the architecture a lot of people tell


me is so much simpler than event


sourcing but I don't know if I can


believe that because here is the same


approach in event sourcing you handle


your command by projecting your entity


and I'll explain what a projection is in


a minute you accept to reject the


command just like you did before you


write an event or you you build a


deposit event I should say and then you


write it to the database your event


store and that's it and that projection


that I talked about is really where we


gather all the events that pertain to a


single entity or model if you're in in


rails land you gather them together and


you you reduce them down or distill them


down using a projection into a single


entity or perspective of of what that


entity is derived from the events and so


when we've when we've written events to


a stream and we want to project it we


can kind of visualize that we're reading


a stream sequentially because that's the


way we read streams and when you're


projecting entities you always start


with a blank or empty data structure for


your entity and you sequentially


traverse each event one by one and so in


this case we start with an opened event


and we copy some attributes over and


next we read a deposited event because


that's the next event of the stream and


we increase the balance by 11 dollars so


it goes from 0 to 11 and then we handle


in withdrawal for 10 dollars so it goes


the balance goes from $10 to $1 and so


on and so forth so that is the talk I


think if anybody has any questions


you're welcome to ask


I'm a little bit early on time no no I'm


I'm here to talk about all the things


that can go wrong once you decide on


this architectural style in fact there's


a lot of common anti-patterns that and


mistakes that I've seen teams make and


it's Costin time and money and usually


they all stem from the same source which


is continuing to perceive our software


or the way we develop software from the


lens of the ORM and and really I what I


want to say about this is I'm gonna go


into the anti patterns there's four I'm


gonna bring up and the important thing


to note here is mistakes are a lot more


costly in an event source system because


your database is immutable and what that


means is if you make a mistake in your


software when you're using a relational


database you can you can go and change


all the data to correct it and


compensate for that mistake but if your


database is immutable you really you


really don't have that option there are


approaches and techniques to remediating


bad data in an event source system but


they all much more much more expensive


in terms of time and cost so if you


follow these if you follow if you avoid


these anti patterns and pitfalls it


doesn't guarantee success but I think


you'll be better off if you heed them


so the first dating pattern I want to


talk to you about is entities that are


aware of the messaging around them and


typically in events or systems we we


handle a command message or a candle


command and we publish an event and


usually there's a correspondence between


the command and the event we issue


deposit and we write deposited and all


of that is messaging and the reason I'm


bringing that up is because I first want


to show you what an entity is like when


that entity is unaware or hasn't been


coupled to the surrounding messaging and


it's really nice you can you can


understand and read this code at a


glance in fact it doesn't even need


syntax highlighting and incidentally


Google slides software it doesn't


support syntax highlighting so I really


love it when the universe just makes


things work out but you can understand


and


and and it makes sense and if you've


been using ORM s for a long time you


might even approach this entity with a


little bit of skepticism how can it be


this simple to have an entity of course


when you're done after some time you're


going to have a lot more baggage around


it and that's actually not true there's


a really good point made yesterday which


is your entities or core business logic


that's what belongs in your entities and


yes you can work on and implement


systems where the entities are as simple


as this and they are a lot more reliable


and they're a lot easier to work with


and you can think of messaging as


periphery that integrates your entities


with your user interface in front-end


other entities you know your underlying


operating system other databases other


you know other other concerns and once


we introduce the the concern or the


responsibility of messaging into our


entity we see very very immediately that


that the the the entities cohesion has


been has been reduced substantially


we've got these unrelated issues so this


method deposit now takes a command


message as a parameter and it actually


it actually decodes or interprets what


the meanings of the attributes on that


message are and that the interpretation


of what a message means is a messaging


concern it belongs in a message handler


and this entity also returns an event


and when you when you build an entity


that is coupled to event sourcing then


you've really then you really put


yourself in a situation where this


entity can only be used as long as


you're doing event sourcing and you must


always be aware of a net sourcing when


you're in understanding and interpreting


what this class does and in reality the


entities that I build that don't look


like this I could switch from event ID


over to ROM and keep the same entities


and everything around that is how we


integrate the entity with the rest of


the system and your entities are your


most core business logic and they're the


they're the biggest strongest asset that


you have it an entity in fact if I look


at the previous one this almost you can


read it and read it as a specification


for what an account does as it pertains


to deposits and withdrawals


so don't give that don't give that up


easily so the next anti pattern that I


want to talk about is view bias to vent


schemas and this one is I'll just


explain what I mean when I say view it


is very simple anytime we're displaying


information for our end-users whether


it's auditory or visual we're presenting


them a view of information and


oftentimes those views contain data that


that actually in its authoritative place


lives in multiple different event


streams or some of the data might be in


an event source system and other data


might be in a relational database so how


so so building views typically with


event stores doesn't work out too well


because our event stores that we use for


storing events are log structured and


they can only be queried given an


entities ID so we can't say give me all


the accounts that have it have had


activity in the last 90 days relational


databases are really good at that


they're also really good at tying


information from different parts of your


domain together to and joining them to


present a single view so when we build


events or systems we typically when we


write events we typically handle those


events and update and build materialized


views out of them and if you're familiar


with DDD you probably or you might be


referring to these as these databases on


the right side as read models which is


another term form but I just call them


materialized views because that's what


they've been called for the last few


decades so if if this slide resembles


the original side I used to demonstrate


projection it sits on purpose projecting


events into a view database or a


materialized view is really not a whole


lot different than projecting them into


a data structure an entity in memory so


here's kind that's the background for


this anti-pattern but but I'm going to


give you a specific example here we have


an account transactions table and a


transaction categories table and this is


this is the view that we want to display


for our end users we have individual


transactions but they each have a


category ID and that category ID


and be used to join to the the


categories table and give you the name


of the category so we can figure out the


first transaction was an $11 and 11 cent


purchase of office supplies for instance


so the problem that we we typically run


into when we start building events or


systems is for the first time as we


realize I'm trying to project this


withdrawn event for instance and the


view I'm trying to write to has this


column for a category ID and I haven't


got a category ID on the event that I'm


that I'm dealing with and that's that's


an immediate problem you don't know how


to get it there and the the tendency or


the temptation is let's just change the


event scheme and attack on the category


ID so that it's there that when we need


to assemble the materialized view and


the problem with this is the the problem


with this is the dependency direction is


going the wrong way right we're


designing our events our core which are


part of our core domain we're designing


them to serve our UI and the data that


we need to display and when I said


earlier that changes to your events in


your event schemas is like with the most


expensive thing that happens in these


systems this is this is really


interesting because I've added a new


reason for this schema to change if your


categories are being applied for


instance based on some heuristics that


are determining oh you bought this you


bought you made this purchase at a


grocery store it must be food you bought


this purchase at an office supply store


it must be office supplies if that


heuristic algorithm changes these values


might change and so that might


invalidate the data that you've written


in your existing events if you were to


add category ID to the event so you


really want your events to represent


what occurred and nothing else that's


it's very important there are raw truth


of what happened there not a vehicle or


a conduit for you to shove in other data


so that you can get the whole end-to-end


experience working that's usually the


number one thing that people coming to


coming to event in systems deal with is


they want to figure out how to build the


whole UI all at once and that whole


getting that whole picture to work


immediate immediate


there's a lot of obstacles like this in


their way and I want to kind of I want


to kind of talk about this word tie


because I think it's it's slang that we


use very often to talk about how


different entities relate to each other


and that relationship is really a


relational database way of thinking and


and this is an example the tendency and


the temptation for us to do this is


usually a carryover from our mentality


of building systems on top of relational


databases and and and or eum's so the


alternative here that that works a lot


better is to compose the whole view


database from different events and


isolate where where events are coming


from so that they don't have to all be


in the same event or the same stream and


there's there are also additional


techniques to aggregate your events so


that you could produce any kind of


schema you want including a view


database that combines a category ID


sorry I misspelled it there category ID


with your transactions but I'm not going


to go into that because we don't really


have the time there's a variant on this


this anti-pattern where people come from


rails and they're used to the error the


errors object and they're used to using


the errors object to show validation


errors in web forms and they want that


because that's that's how they're used


to making their UI work and the problem


with this is your error is a really it's


a disposition it's a negative


disposition as Nick was saying it's the


left-hand path and that's a that's a UI


concept when when funds you know when a


withdrawal caused somebody's account to


go into the negative because they didn't


have enough balance that's not an error


from the perspective of the bank that


collects $20 every time or 20 euros or


whatever every time somebody goes


negative so we don't disposition events


as being positive or negative that's a


UI concern and we have to build to build


systems this way we really have to start


distinguishing our user interface from


our back-end systems or


our core logic or domain the next


anti-pattern is opaque dependencies and


by opaque I mean you can't see the the


traditional meaning is you can't see


through it but what what it really what


it really connotes is that you can't


control something or that it's implicit


or it's out of your hands and opaque


dependencies can cause real problems and


just about well in really any kind of


software system but an event sourcing


they crop up in a couple ways the first


one is making your projections opaque in


other words hiding the projection so if


you if your command handler accepts as


input the already projected event then


you hat you cannot control the


projection and there's a couple problems


with this first of all this is


terrifying for beginners because they've


just learned about event sourcing and


then they go into the code to understand


how it works and to see how it happens


and they can't find the event sourcing


anywhere it's actually in the bowels of


some framework that is that is external


the other problem is that you can't


control the projection directly so if


you want to introduce in 2d caching or


you want to change the caching strategy


you have no means of doing so without


the framework also affording indirect


control through settings configuration


class macros or gasp global State we all


know a global state is a bad idea right


yeah ok so the other thing the other


reason this is a bad ideas there's


actually plenty of situations where


entities are not even necessary when we


typically when we are for instance


ensuring that an email address is unique


and using events tour databases we write


a reservation event it's good we call it


reservation pattern but this particular


approach for validating uniqueness is it


doesn't depend it doesn't need an entity


and so you'd have to construct one if


your framework forces you to have one in


your command handler and incidentally


this approach to uniqueness is a lot


like the rails one but it doesn't have a


race condition in it what that validates


uniqueness of does


the the the the other situation that I


want talking about is when we're


updating those materialized views when


we were materializing those views the


entity is a view entity and it's


actually data living for instance in a


relational database if you're using a


relational database for your for your


read model and in those cases you have


no entity and and and the final one


sometimes we have just telemetry


handlers that for instance every time


your your company receives money from a


payment you might want to record a


metric or record a signal sorry


telemetry is if you think about an


airplane and every time an airplane


crashes which is thankfully pretty rare


there's that black box that they recover


from from the plane and that black box


contains the telemetry or all of the


information logs of what happens and it


can be studied for root cause analysis


of why the plane crashed yes yes and and


I kind of I kind of used the every time


a purchase is made you want a signal as


an example but in reality telemetry is


more of a lower-level concept where we


want to see how long our message is


taking to get handled and what's going


on in the system so the next kind of


opaque dependency is an opaque writer


and in this case we we we just watched


NYX talk and we got really excited about


functional programming and we said you


know I don't really want my handler to


write events at all


I wanted to receive as input a command


and return as output events and


unfortunately there are a couple of


problems with this approach you know I


want to say first of all when when if


the handlers job is to accomplish


writing an event the handler isn't done


until the events been written so so the


handler is in this state is incomplete


because it's returned


it's a returning event but the event


hasn't been written and and databases


are unfortunately running on computers


with electrons and writing to the


database can fail


so when your handler hands off the


responsibility of writing the event to


some external actor then that external


generalized actor has to end up figuring


out what to do if there's a failure


which is very unfortunate and again


another sign that that this handler


hasn't done its job hasn't completed it


the other thing I want to say is there's


a lot of variations to how we write


event an event sourcing it's not as


simple as returning events one of the


first one of the first parameters that


tends to come into play when we exercise


writers is something called expected


version and this is a little bit more


technical but it's it's a means of


concurrency protection so if you have to


if you have the same if you have two


passenger threads let's just say


accepting form submissions or commands


that pertain to the same entity at the


same time there's a race condition which


one is going to be first and the


behavior of the whole system might be


different depending on which one of


those threads wins and so expected


version is an important countermeasure


for being able to deal with concurrency


but it's also very important that it is


not used in every case because if your


Handler on the other hand issues for


instance an API call to stripe charging


somebody's credit card then you don't


want to introduce any reason why that


right would fail because if you charge


somebody's credit card and then you


don't record any event that says you


charged it then you're prone to charging


them again because you've forgotten that


you already charged them


and all of this to say is sometimes you


need to set expected version and


sometimes you don't which means


returning events from a handler is is


improper it's it's it doesn't allow you


to control it and there's other


variations to writing that I won't go


into but suffice it to say your handler


must be able to control the writing of


the message because it's not


generalizable the situation's the


different situations call for different


means or different techniques when you


write events and the common theme here


is we need to be able to control our


dependencies


and and I think that's one of the most


fundamental aspects of software that is


is oftentimes overlooked by teams


because they've never done it before


we've we learned how to install gems


like VCR that can step out Network calls


for us so we don't have to control our


network interactions we mock the


database using global mocks so that so


that we don't have to control whether


our object interacts with the database


or not and as you build more and more


complex as your systems grow in


complexity your need to be able to


revisit earlier classes that you wrote


six months ago and test them and


exercise them in all the different ways


that you might want to that that ability


is severely severely diminished if you


can't control the dependencies and in


fact in our systems when we test our


handlers let's see well this is not a


great example when we test our handlers


we never hit the database because we


don't need to because we have a


substitute writer that we can that we


can control we can control the handler


and change its writer to that of a


substitute alright this is where I pick


a friendly fight and I'm gonna I'm gonna


call out the aggregate root class


pattern and it is if it is a friendly


fight I promise but I have I have seen


this pattern used by multiple clients


and I it has had it had very unfortunate


consequences in in every case and to


explain explain what I'm really talking


about I'm talking about classes that


that mix the responsibilities of an


entity and the responsibilities of a


message handler and the responsibilities


of a projection into one and this is


ostensibly done for convenience but it


it causes us as I said earlier when our


entity starts to become concerns with


all these other things like messaging it


stops - it stops being an entity


altogether it stops being something that


you can look at and recognize as an


implementation of your domain model and


one of the major benefits that we get


with event sourcing is lost when you do


this


because when you can build and test your


entity in isolation without needing to


instantiate events and when you can test


your projection by simply giving your


test an entity and some prior state and


an event and testing the next state and


when you can test your handlers by


simply controlling the current entity


and asserting on on what was written


when you can't do that you're missing a


big opportunity because when you can


these systems become very easy to reason


about and understand and I want to kind


of bring up another question that is a


little bit uncomfortable it's why are


aggregates so popular why do I see these


everywhere everywhere I go where people


have already started using event


sourcing and I think I think that


they're even outside the rails community


I think the vast majority of web web


developers have very little comfort with


object-oriented programming I think


they're used to procedural and


declarative interfaces where you you


subclass a framework artifact like a


controller and you insert your code


there and you don't really think about


what is the structural design in my


system


you don't move concerns into namespaces


very very often and so by moving all the


responsibilities into one class one


aggregate class you're increasing the


comfort level locally or in the short


term and I think that's the


justification but I don't think it bears


out to be to be that beneficial in the


long term and and at a variant of this


I've seen is a lot of a lot of teams


even even more experienced people will


justify this and say well in the


beginning you don't know what your


boundaries are and because you don't


know what your boundaries are we just


want to hack some code together we want


to we want to iterate and then we want


to refactor later when we know those


boundaries and the problem with this


thinking is that it's backwards it's a


lot like if you went through your house


and grabbed cleaning supplies under the


sink and then you bought some test tubes


and beakers from Amazon and then you


poured all your cleaning supplies and


test tubes and beakers hoping that you'd


get a scientific discovery coding is not


a practice that leads to an


understanding of anything it's a


practice it's what happens after we do


the engineering and decide what it needs


to be and what it needs to do so there's


a there's a organizational maturity or


industrial or professional maturity that


comes when we understand how to


distinguish banging on keyboards to


produce an implementation from closing


our laptop lids and maybe getting in a


whiteboard and figuring out what the


system is supposed to be with our team


and the other reason I think these


approaches and really the aggregate


class has has involved all the other or


most of the other ending patterns as


well a lot of times it's community that


really leads to the proliferation of


these patterns and community is


unfortunately a word that only seems to


have positive connotations and I think


that that's I think that some of that


positivity is fair because communities


can be wonderful this is it's supposed


to be animated but it's not animating


this is these this is a group of Amish


in Pennsylvania United States that are


building a barn in less than 24 hours


and actually there was recently a


hurricane in Texas where I'm from that


not where I live but in Houston there


was there were just tons of houses right


on the oceanfront and I think I'm close


to time but I'm gonna keep going anyway


there was many many houses that were


just blown away and and these Amish


people actually left their homes and


families and and spent a few weeks down


in Texas helping to to clear out these


old destroyed homes and replace them


with with well built the Amish are very


good builders and that's wonderful and


inspiring and it should be inspiring but


communities can also be incredibly


harmful they can lead they can cause


psychological triggers that really


subvert our critical and rational


thinking processes and they can lead us


to not question things and most


importantly when we when we have


communities we usually have community


leaders and when we have community


leaders we trust them and that means


that when they espouse ideas we we hold


those ideas under less scrutiny and then


they can they can become popular and I


don't think this does a service to


thought leaders and I think


you know if I I could probably give you


a list of a hundred really terrible


ideas I've had in the last two years or


ten years that my colleague Scott has


helped to disabuse me of and this is


what we want we want we want to feel


comfortable having bad ideas be called


out by people in a friendly way and when


you don't have that people follow the


rails way for instance even though it


leads them to ruin and it's interesting


you know I what I've seen in these


events sourcing implementations that use


aggregate classes is they can't stand


rails in fact they're a little bit above


rails they're a little bit better than


rails because they've learned why rails


sucks and and they say real sucks we


have all these god classes and nothing's


nothing's well-designed or modular and


then and then we look at the


implementation and we see God classes


using event sourcing and you got to


wonder if if you're thinking about the


tooling being the problem


remember the tooling never forced you to


build a big monolithic application that


you can't change that was you and if you


don't correct the thing the mistakes


that you made you're gonna make them


again and if you think you're going to


move to a lick sir for instance and


you're going to correct all those


problems because elixir doesn't have


them then then you haven't really found


the root cause so I think it's important


to always scrutinize popular techniques


and methodologies I look forward to when


I'm done checking checking the hash tag


for everybody telling me why I was wrong


I I really do look forward to that and


and be aware of of how difficult this


stuff is and also be aware of your


understanding of complexity because I


think what happens what happens and


causes people to stick with monoliths


and make them happy with their monolith


is because they feel like when I start


to partition my system or I start to


approach new styles I see more


complexity I see projections and and


entity cashing an expected version and I


never used to see those things with


rails and active record and the problem


is is yes there is there is an increase


of complexity as we add these patterns


but it's not complexity that you always


have to remain


Arif its contextualized complexity your


operating system is incredibly


complicated


Ruby's virtual machine is incredibly


complicated web browsers have tens of


millions of lines of code but you you


really only deal with a subset of their


a small subset of their complexity so


when we're building these systems and


composing them of these these modules


and we're using event sourcing for


instance for not only persistence but


but communication between these services


you are adding complexity but you're


also you're also allowing yourself to to


safely disregard most of it at any given


point in time and the kind of the last


message I have is I really I really


believe in this after this phrase which


is measure twice cut once there there


was a time when when when we criticized


waterfall and we jumped into agile and I


think that that was very positive but


that was at a time when it was when it


was typical to spend six to eighteen


months in upfront design and now we're


at a place where the community is


usually uncomfortable with more than 6


or 18 minutes of design and I see it


over and over again with clients if you


spend a week a week designing just one


service and then you maybe spend one


week or two weeks including that one


week will be hell for people that are


not used to designing things and they'll


call it waterfall but it's not waterfall


it's not six months it's not 18 months


it's a week of closing your laptop and


figuring out what's going on and that's


what you that's the fundamental


philosophy that you need to adopt to be


able to succeed and that's all I got


again I'm a trillion TL on on Twitter


event ID is the project I'm a co


principle co-founder and please check it


out i welcome you to we're we're working


on documentation and it's in progress


and we're not really interested in


releasing a1o until until we have


release documentation so that


everybody's comfortable you know so that


we feel comfortable asking for adoption


so it's coming soon we have used it in


production quite a bit though so anyway


that's it


q thank you all I appreciate it


questions


she won't explain even something to you


again but you can start what is an


entity is an entity like an object that


has attributes oh is that a process


I usually when I'm talking about an


entity and I'm talking about the code


perspective I'm usually talking about a


data structure with with methods around


it that that for instance is it when I


showed the deposit method that that


increase the balance that's an entity


it's a data structure with Metin with


domain specific methods there's also


other perspective entity like a logical


one


so an account micro-service might might


actually be thought of as an account


entity if you zoom out enough which is a


subtle point but usually I'm talking


about the code pattern so could you


actually show this slide with this


entity and how you handle the event well


handle the comment wait this is the


wrong one right the one where we had a


handler yeah I think it's this one this


is the yeah this one is okay so usually


in many cases you would have more than


one such if statement so the reason for


withdrawing the command or rejecting the


comment might be more such reasons so


don't you think this will end up with


the feature env smell that you asked the


object things and things before you


actually tell the object to change


something yeah actually this is


something it's come up before which is


if you if you if you want are aware of


the principle and object-oriented design


tell don't ask you're identifying a


query where we ask the account if there


are sufficient funds and and it is


possible to tell the account to make a


decision based on whether there's enough


but the problem is is the outcome so


this is an if-else and and the outcome


of this else is deciding which message


to write and that's a messaging concern


and I think it's it's a little bit


taking encapsulation too far the idea of


encapsulation too far to say that you


can't ever have a query method this is a


method that returns true or false which


is necessary for an application to


decide what to do because we can't


generalize what action to take they


whether an based on whether there are


not sufficient funds I think like this


is exactly the place where I agree with


the way you describe the aggregate root


problem because in I agree that it does


couple the entity logic with the


messaging layer however I think this is


the decision that we want to make


whether we want to expose many query


methods and go with the query approach


overall or go with the you know telling


the objects what to do and then you need


to couple because that was like the


aggregate root for example as in receive


and store this was a design choice to


eliminate such code so that's the reason


we have the messaging couples to with


entities yeah I don't have so that so


the best answer I can give you is that


there is an if-else that belongs in this


handler because the handler has to


decide to write withdraw withdraw


declined or withdrawn and so so that if


else or that conditional belongs in the


handler and so so the best that the


entity can do is give us a yes or no if


there's sufficient funds now in the case


of withdrawing funds there's only two


outcomes you either had enough money or


you didn't and in other context there


might be many more outcomes and the the


the answer that event ID has for that is


is that event ID has no answer it's it's


up to the programmer to determine how to


manage that complexity so I think that I


can't prescribe a one-size-fits-all


solution there yeah just in my


experience like I wanted to avoid such


code because what if it's just one


if-else that's okay but usually we you


have like a more more nested if


later on and then then this this code


doesn't look released at school anymore


well I so so um I'll say that when I'm


in now


so before this code gets written there's


an analysis there's an analysis of what


does what happens when we handle a


withdrawal and we already know where


we're going to get to because we're only


analyzing accounts we're not analyzing


the whole system and so we put an


account accounting system that's very


similar to this into production and yet


we didn't have to make one code change


to it aside from one minor fix not it


wasn't even a fix it had to do with


something minor I can't remember now but


by and large we didn't we didn't we we


designed our accounting service and we


deployed it and we didn't have to add a


single conditional for years afterwards


and that's because we understood what is


innate about account withdrawals


so we epitomized the essence that we


append mais or captured the essence of


what withdrawals were and that's that's


why we arrived at this F else it's this


is not a pattern of this else if else


that always goes in can in handlers its


frequented handlers to have left or


right as Nick was saying earlier but


it's not it's not the only way or it's


not the only pattern that emerges so I


guess my my opinion there is as long as


your handler is in control of everything


that it needs to be in control of you


can tackle that complexity however is


appropriate for that entity which is not


a really good answer but the answer


usually isn't isn't that great or it


requires you to figure out what's best


for you so what is currently your


biggest problem and you're dealing with


now the biggest challenge with this


approach oh man now we got to get real


huh


everything's perfect


so here's here's here's an important


there's a couple of realities number one


you will never build you'll never be


able to prototype with these systems as


quickly as you can prototype with rails


that is it is impossible so when you


need when you when you need to sketch


when you want to sketch out a small web


app or or whatever it's it's it's now I


will say I will say I you know you can


you can still implement these pretty


quickly and in some it in many cases it


is just as just as it happens to be just


as fast but we don't aim to be the


shortest path to implementation I'm


trying to understand the transactional


property of that flow because when when


you record the event like we've drawn


you or we've drawn declined it it has to


be cobbled together with the actual


withdrawal that happens in a external


system or something but you still risk


that the other the actual operation will


fail so I'm just I'm just curious how


how do you guarantee that that's the the


action of recording an event like we're


all is actually connected with the real


operation may be yeah this happening


manually right they could the wire the


transform my phone whatever right yeah


well I think there's two considerations


here number one this system might be


authoritative over account balances in


which case there is no external call a


number two this is sketch code which is


which is really incomplete from an


implementation perspective because it


doesn't consider idempotence what


happens if we handle withdraw more than


once and unfortunately there just isn't


enough time to go into patterns and


techniques for idempotence but they're


there there is a little bit more to


building these systems but not much more


if right right so if a withdrawal can


only be achieved by sending and


submitting an API requests for instance


to a third-party service then that has


to happen here and also that decision


about sufficient funds does not happen


here because because we because wherever


the data is authoritative


that's where decisions could be made


around the data so you can't make


decisions locally around somebody else's


data and that somebody else could be


another organization and it could be


another service but we are you know data


that changes together stays together


and also decisions based computational


decisions based on data belong where the


data is authoritative official fellow


thanks for the talk I'm wondering about


this line when you do an event time and


set in current time to this property so


that it means that there is a ordering


of events which relies on the time no


okay so what do you need is well and and


well I will say is is what we typically


when we typically sign an attribute


called time we're talking about a


timestamp when the event occurred but


there is no necessary reason to assume


that the order of the events in the


database is the same order as the times


of all the events


it just is just a meta information okay


I guess that is it so then the next


question so you get a distributed system


so how do you order the events happen


different system and the answer to that


is to use a very technical term that is


you don't need to understand this


because there's better ways to learn it


but the technical term is vector clock


okay I guess yeah but expected this and


you get something you yes but I actually


when we teach when we teach when we do


we put on workshops and we haven't done


one in Europe yet someday I would like


to but when we teach this stuff we don't


teach people vector clocks we teach them


how to have the underlying problems and


then and then


to solve them with the tools so yes it


has a vector clock but do not be do not


be scared off by that turn sounds great


actually hands banks yep


I'm just wondering when people from


rails start to use event ID do they I


mean it's probably an anti-pattern in do


they happen to write those handlers


instead of controller actions because it


looks like you know they will add all


the code to the handlers basically and


then treat requests basically like an


event is that something that happens or


well the first decision that they that


that people are trying to adopt event ID


within the context of rails will the the


first decision that they'll one of the


first decisions they'll face is whether


or not to have their controller actions


write a command message to a stream or


to handle the command in the request


response cycle and I will say that if


you're planning a transition to micro


services you're better served by writing


the command message because then your


implementation is fully portable you can


take it out of that the context of your


rails app or your hanami up and it'll


just work if you set it up right does


that answer your question yeah there was


a hand raised up there at the top not do


you I got you in the back man


[Music]


how do deal with event versioning I mean


what if the scheme of the event changes


yeah that's a really good question so


when you do when you do realize that you


wrote some events with with a schema


that you don't want to live with and you


want to change the event schema that's a


difficult situation and there are


countermeasures when you're built when


you're doing event sourcing in the


context of a monolithic application a


versioning is really usually the only


option you have so you have to so you


have to publish new versions of your


events and then you have to every time


you handle events you have to figure out


is this version a or B and then you


to perhaps take different take a


different action there one of the big


reasons why we use invent sourcing in


conjunction with micro services is micro


services are generally small enough that


they can be reimplemented very quickly


so if you if you identify that micro


service wrote events that were wrong


enough that you need to change them that


you can build a new micro service and


then you can take the events of the old


and then transform them into commands


that you feed into the new which is


still a lot of work and it's still very


difficult so my first answer your


question is don't make a mistake and and


it's it's it's hard to hear that as


software developers but every day


millions of Jets fly you know fly around


and take people from point A to B and


they usually don't crash you know well


yeah and and the industry of airline has


learned from their mistakes one of the


biggest and you're getting me started


now one of the biggest problems with


software is we don't learn from our


mistakes instead we switch programming


languages we switch tools we switch jobs


we do everything we possibly can to


avoid facing up to the fact that we


screwed up do you typically use


centralised even store or a different


approach that's a that's a bit of a


loaded question because I think in the


microservices world there's a there's a


concept that each micro service should


get its own database and there is a lot


of Merit to that in the context of


relational databases because those


associations that that connect one table


to the other those associations will


prevent you from drawing service


boundaries because you'll have to have


that data to be in the same database in


the case of event stores they don't


offer associations and they're naturally


isolated at the stream boundary


therefore there's really no harm in a


services architecture of running all of


your services against the same physical


event store that said it's up to your


operations people to decide you know


what our account service is experiencing


a high volume of transactions and we


need to scale and one of the first


easiest things you can do to scale is


move that database out so that all of


your other event traffic is not


interfering or slowing down your your


your account traffic for instance oh


goodness


keeps going love it I love it hi I have


a question if you keep your data as a


series of events do these events contain


the latest state or each of them somehow


contains the change of a state and if


you want to get the current state do you


need to somehow calculate it from the


couple of events or do you have some


single source of truth current one and


if not how does this potential


calculation effects performance if you


need to


you cannot just read it you always have


to calculate it here yeah I think I


don't get it so that's a good question


to get to go back to the beginning of


the talk we do store and persist as


authoritative data the the events that


rep they don't represent the current


state they represent just what happened


and in order to arrive at an entity in


memory that represents the current state


we have to read each and every one of


them sequentially and this does present


a number of performance considerations


but fortunately there are very readily


generalizable countermeasures for


instance if you'll notice each one of


these events has a position that's


exactly one greater than the previous


one and that means if I project this


entity up to the withdraw an event at


position two I can store a cash record


that also includes hey this is version


two of the entity and so the next time I


read that entity I can pull a version


two out of the cash and then I can start


reading from three onwards so we can use


cat we can use caching transparently


to solve that problem and then there's


another performance issue of well if you


accumulate one event for every time


something happens then you're you're


using a lot of disk space it's relative


to if you only stored the current state


and there's countermeasures for that too


but I am going to so one more question


do you have some kind of caching


solution baked into your gem or deserves


to somehow do it from scratch phew yeah


no event ID is a collection of libraries


and there's a gem called entity store


and this is this is a little bit of a


bastardized example of it normally we


build it and and use it as a dependency


and you're seeing it references a class


here but the entity store library


already comes with a cache and in fact


that cache has a means of introducing


snapshotting as well and what


snapshotting is is if you have us if you


have a stream with a million events in


it when you restart your server you


don't want your server to have to


project a million events the first time


it's accessed so we can periodically


snapshot and that means write a


representation of the current state of


the entity every hundred or every


thousand events so that's another


countermeasure for the performance


issues thanks so how do you deal with


the gdpr like the data protection like


requirements that are like in your


theanine now yeah okay but we can use


the Evenstar syncing new Europe also so


yeah sorry in America we can kind of do


whatever we want


like and regulatory requirements are


part of your business domain they're not


part of a framework so when you and I've


actually I I joke but I've worked in


healthcare industries and we do have


some regulations most of them were


designed to prevent people from


competing with the big corporations that


run everything but there are regulations


and and you have to model them in your


domain but I I haven't encountered a


situation before where we're following


regulations was a difficult thing to do


with with our libraries or with event


sourcing thank you


[Applause]