45a13664
extracted
Łukasz Reszke - Working with RailsEventStore in Cashflow Management System - wroc_love.rb 2023.txte149bb9ff8b9| Status | Model | Tokens (in/out) | Duration | Cost | Nodes/edges | Read set (nodes/edges) | Time |
|---|---|---|---|---|---|---|---|
| completed | claude-opus-4-7 |
642,636
/
14,288
173,434 cached · 11,306 write
|
230.6s | - | 15 / 49 | 196 / 2 | 2026-04-17 22:12 |
| failed | claude-opus-4-7 |
RubyLLM::BadRequestError: You have reached your specified API usage limits. You will regain access on 2... | 2026-04-17 16:18 | ||||
yeah there is one fun fact about wukash
uh
who can guess what was the programming
language that Lucas used two years ago
yeah so ukash was a dotnet developer two
years ago and I'm really happy that I
helped him to convert to Ruby so
um
yeah so ukash will talk about a real
world project that is happening where uh
relative and store was introduced or
more more in general even driven
architecture was introduced so really
practical situation I I hope some of you
will
um yeah do something like this as well
in your projects sooner or later so yeah
let's welcome mukash and good luck
thanks Andre yes I have to admit two
years ago I was addicted to.net and so
he took me out of this
I'm really grateful uh yeah so uh it's a
big pleasure to be able to speak as the
first here in this conference I'm first
time here guess why
also.net developer uh but yeah I will
tell you about how we work with res
event store in cash flow management
system
you already know my name so I can skip
this slide I work in Arkansas company on
a daily basis we save Regis Legacy
projects so if you have any issues you
know where to hit us and in this talk
I'll tell you about six stories about
how we work with race event store in
trezy the cash flow management
application
and uh it's good to start with with what
this cash flow management application so
this is the application which helps your
small business to take care of your cash
flow you can check out your bank account
balances in one places we also do some
accounting for you so we don't have to
wait for your our content to do it once
or twice a year which is usually the
case and the race event store is an open
source implementation of even store for
Ruby and rails established in 2014 and
it acts as a library for publishing
consuming storing and retrieving events
and in this talk I'll be mostly talking
about even sourcing in combination with
event driven architecture and also there
will be a tactical domain driven design
pattern and also tests tests will be
really important actor of this
presentation
so is anyone of you familiar with this
picture please raise your hand do you
ever see it yes some of you will not
talk about that so with this background
set let's go to the first story which is
called the one with the open banking
provider
as I told you we are cash flow
management applications so we need your
bank account data right but we don't
write the integrators on our own we use
third-party providers so-called open
banking services
and those Services send us the data so
for example we can show you the balance
of your all accounts but also your
transactions and so on
based on this the data this information
we can calculate useful reports for the
small businesses that use strategy and
the banking providers integrate with us
through so-called web hooks so they
basically hit our API and they send us
some data in the payload and there are
at least two approaches that one can
follow to process a web hook first one
will be synchronous approach so when we
receive a web Hook from the banking
provider into our rest API we can pass
the payload from that webhook like a hot
potato until in Lance in the loving
cameras of the database but and it works
it's good but the question is what if
something fails on the way to the
database for example in the application
layer
and there's a lot of things that could
go wrong here for example well we just
may violate some index the schema of the
database might change we may have
processing logic error and so on
so what is what if there was another
solution and for example instead we
could store the payload as a technical
event so there is the first uh relation
to even sourcing right instead of just
saving it into the regular database we
store it in the event store and once we
store it we also can publish it to the
queue and process this process it
asynchronously so this is how it would
look like so when we would um when the
banking provider send us a web hook it
of course goes to our rest API and then
we store and publish technical event
then there is a queue that well takes
this and then there is an event handler
that would be interested in processing
this and getting the payload into the
database together with some calculations
and making useful reports
and there are certain benefits in that
approach first of all is that we have
external system audit log right so we
have all the payload information stored
as our technical events and we can
basically access them whenever we need
or we want to this is very useful for
debugging and troubleshooting we also
have improved performance so the
responses to the third-party systems are
super fast because we don't process any
data right there is no call to the
database we just well there is to the
event store but we simply store it and
then do nothing else we also published
the event but that just takes the
milliseconds and later on we can process
it asynchronously based on the
processing units availability and what
is really cool about that is that we can
scale our web server which is receiving
the web hooks right independently from
from the web jobs so we'll probably have
more web jobs processing the web Hooks
and not the like many web server
instances and the last but not least we
don't have to rely on the third party
retry mechanism because once we have the
payload stored if something goes wrong
I can always access this right it's
already mine I could say so if there is
a bug I need to reply my code I can do
it whenever I want I can try as many
times as I want and
and I don't rely on the third party
provider and when they send me a retry
payload and because they may never do
that or they may do that in couple of
hours and I may need it as fast as
possible
so this is helpful and keep that in mind
as in the next stories I'll be referring
to that
and let's go back to the open banking
provider once again so I said that we
decided to move processing of web hooks
into US async processes right so one
question pops up in mind what could
possibly go wrong here right
because there is no such a thing as a
free lunch there are a few awesome
benefits that we have but also there is
a drawback the problem is that the web
hooks that are now represented by events
May Come Out of Order
right
it may change it's not guaranteed so and
the order matters and consider following
example
when there's a web hook received with a
balance of bank account for 100 and then
we start we publish it as a technical
event we also store this information
and we failed processing this webcook
and then another one comes for the same
bank account with other balance
we publish it as a technical event and
we started processing it we processed it
successfully and then we start once
again processing the first one
we just overwrite the data
we don't want to overwrite the data so
we need to solve this problem and I
think it's also a good moment to stop
for a second or maybe for a minute as
the slide says and I want to tell you
about the project that we work with
because some of you may think that well
I it's a green field but no it's not
it's a code written in a startup way and
I think that a picture explains more
than a thousands of words so sometimes I
feel like this well I want to change one
really small thing I have to watch out
do not lose do not just you know break
some other house electricity
um
so what does it mean in the code reality
for the most of the concepts in the
system there is one relational data
model that represents this entire
concept we call it logical coupling
right and I will not fool you it's a
common think interesting and that is
fine because it did the job it earned
the money it made us go forward but now
when we know it extending that model at
this point of time would be wrong
because we already knew that it is too
big and uh
now when we need to add another column
and another information to it it
wouldn't be good solution so
instead of we decided to go on with a
new moment model and after a few
iterations and we came up with something
like this so
um basically the white boxes is the
information that the class needs so it's
quite not so many right because it's
only external provider timestamp the
status and ID of course we always need
an ID right
and it has three operations so I will
start from your right side so the open
method which basically opens the bank
account it's used when it's created as a
new one close method which closes the
bank account meaning that we shouldn't
process any more web hooks in here and
perform an operation and there you can
see Yellow Boxes the yellow boxes are
the rules so once again we used even
storming notation here and the first
rule is saying that I can perform an
operation when the bank account is not
closed
the other one says and this is the
problem that we are serving initially is
that I cannot process this web hook if
the timestamp is older than the
currently applied right so this is going
to protect us and this is how it looks
like in the Ruby code so some of you
have attended the workshop may be
already familiar with that but what you
can see here is that this is a very
simple Ruby class
it contains
the it includes the aggregate route game
but you don't necessarily need that but
it allows us to use the on and apply
methods which are used to deal with the
events on method is kind of applying the
event state to the class itself apply is
storing the event and later on it's also
used to published so as you can see this
class is even sourced and it has one
simple task to do
it only checks whether the operation can
be performed or not and that's it
but I have to admit something we had to
be really pragmatic here and but because
we didn't have time to rewrite half of
the system and you know do it by the
book as with the first picture that I
told you that we'll not talk about
where you normally have to write to the
aggregate or in your right model
basically in one transaction and your
read model should be updated like in
eventual consistent manner right we
didn't do that we didn't have time for
that so what we did instead
we have to be pragmatic and you write to
the bank account this is the top sorry
to the new model which is on the top you
can see the stream and ifra infra
aggregate route where we instantiate
this class and then perform the
operation should look common and then
there's this block of code where we just
add the read model information
and in my opinion this is good because
it's hard to always be perfect in real
project not in a demo one and to follow
all the patterns from the books that we
see at least from the scratch eventually
we may get there but those things evolve
and sometimes it's just not possible to
do it from the scratch and
there are so few assumptions here the
assumption is that the stream will
always tell us the truth because there
may be multiple reasons to change the
bank account state for example if we use
a soft delete with actors paranoid game
which we unfortunately unfortunately do
then it may be deleted for multiple
reasons right but when we see in the
Stream the information that bank account
is closed then we know it's closed and
we shouldn't do anything with this bank
account
so
there's another story with the bank
account which I call the one with the
close bank account and missing events so
you can see already that perhaps we
introduced some problem in the previous
story when we implemented the aggregate
that keeps track of this performing
operation
and
so this is what actually happened so
when we receive the web hook and then
the web was published as a technical
event you already know this pattern then
we started processing it but it failed
and the error said it failed to save the
record
I was really surprised
because there was no problems with this
code so
I take a look at the Stream
looks healthy
like the bank account is not closed
all right so I took a look at the code I
did some static analysis based on the
bug and I noticed that it passed this
line everything was fine here weird and
then it failed on the save
and as I mentioned it only happens for
specific bank accounts
yeah that's the true story best thing to
debug ever and to reproduce with test so
what I do
I harnessed the most advanced debugging
techniques
and I reply the event because I can
right it's in my even store and it
turned out that the reef model was
self-deleted for some reason but there
was no close bank account event right
and we should have it because we just
said the stream will tell the truth
so I was thinking like where's this
event and uh remember it was into the
bank account aggregate was introduced to
keep track of that so closing should
always go through the bank account and
in the healthy stream it looked like
this you can see the event on the top I
hope you can see it it says that bank
account is closed
and then nothing is after it because
that's the intention
so I took a quick look around the code
it looked fine
test screen
and you remember that we didn't
separate the recent rights at least not
separately right so it was always going
together in one bank account transaction
and that's actually what happened
someone was introducing a new feature to
kind of close the bank account meaning
that we should ignore all the web hooks
for the coming data why they would do
that because sometimes the banking
provider sends it too much information
sometimes you have your bank account but
also your credit card you don't want
your credit card but hey you cannot
configure that on their end so we have
to ignore it on our own
and uh this feature was introduced but
someone just forgot to add the second
class into the equation so they didn't
write to the Aggregate and right must go
through the aggregate right we said that
it's the source of Truth for this part
of the logic
and one of you could say that it's wrong
that that we kind of have two source of
Truth and I would say in the like most
of the content like in the depends on
which context but you would be right
however we made a conscious decision
that our goal is to keep the source of
Truth in the Stream
therefore there is surprise but human
errors happen right so now it was the
time to fix it and in order to fix it
well first part was really simple right
write a test make it red at the at this
bank account class write to it make it
green
but you can publish it to deploy it to
production okay but now you have to
backfill the data right it's also very
important step in this pattern
and I call it a cost at the point in
time because
like previously I said we couldn't
afford rewriting half of the system so
we used only the part we needed from the
pattern to have this visibility
and
the startup word and the application the
starter what they there's a kind of fast
pace of moving right so there was just
no time and basically the business
wouldn't allow to us to to do such a
modification and introduce full cqs with
two databases and so on and that's fine
because the system doesn't have to
follow one pattern entirely
it can just use the best of it in
current context
oops okay
I didn't touch anything guys
okay
um
so bear with me this is not the only
aggregate we'll talk about uh but first
I want to tell you about the story
with pending transactions yet another
issue that I had to solve uh and where
events helped me so having events in the
system that is asynchronous but also
depends on the external provider data is
very helpful
but first let me explain you what is
what are the pending transactions so one
of the our banking providers notified us
about new feature that hey
there are we can send you transactions
that are not fully processed by by the
bank so your customers can see them
really early on but when we send you a
new batch you are supposed to remove
those transactions
and it's your responsibility it's like
okay let's use it and
after a couple of weeks when there this
was on the production we got the bug
reported by a customer
and they said that they don't see new
transactions the bank account balance is
not right it looks like the old bank
account balance and there was a time
where I was hearing this two or three
times a week and I was like yeah so
another guy that doesn't understand that
we are not a bank but we only act as a
third third party right because we are
not even third party
but
I checked our events I fetched the data
and I noticed that there was a really
huge delay because there was two weeks
of delay 700 transactions missing
and I felt like wow
this is really cool
not so I went to the open banking
provider page it has this nice console
well some of them and then I checked and
they actually sent us those events and
send us those who I put workbooks which
we then persisted as an event so I did a
little bit of debugging I also took a
look at our monitoring system and I
noticed that once again it failed to
save the record
so my first thought
not again but then I was like yeah okay
so someone must have broken it so I get
blame right another even sourcing thing
but it was there was no changes so I'm
like okay they must have changed the
payload
payload look healthy
so once again most advanced the
debugging techniques and I replied the
event and then it was quite easy because
I found it
so as I said provider required us to
remove those spending transactions right
and that's what we did we followed the
documentation we follow the instruction
however those words of deleted
and thanks to the actors paranoid game
which I really hate but it's not so easy
to remove from the project
we run into a small issue
so how do we fix that well first what I
like to do and I encourage all of you to
do when you fix it back write a test to
confirm that you really understand the
bug
then of course you can fix it
then deploy it and now for some of you
it will end you here but I can replay
the event
make it right I don't have to wait for
another web hook right normally I would
have to wait until the bank provider
decides to send it to us and I can make
the customer happy
which leads us to another story with
transactions once again and
this one I called the one with two large
transaction model and classification
so as I told you we have transactions in
the system
and we need to classify those
transactions to calculate accounting to
calculate cash flow and other usable uh
wrap reports for the customer so one way
of categorizing your transaction is to
do it manually so as you can see here I
can select whichever transaction
category I like for my traffic car
transaction traffic R is the car that
you can rent in Poland
so once I do that I checked and I
selected the travel expenses and you can
hopefully see that the first one is
green and the other one is just a border
of green and those means that those
transactions are automatically
classified for the user right
because well we don't want them to do it
on their own that's not the purpose of
buying software so
as usual in monoliths this was built in
the beginning and there was a one model
that keep growing and growing and it
became too large at certain point point
in time and there was a lot of business
logic spread around
like everywhere and the worst part of it
was that it was spread in even handlers
so it was asynchronous
um
and the model it was very flexible
because well you know the just a simple
database model right it doesn't protect
you from doing any rules so it's just a
like blank sheet of paper when you can
basically write anything it will accept
it so it's a DDD at its finest database
driven development of course and
yeah I told you already trade of trade
of trade-offs we are this was a startup
they had to do it quickly and but at
certain point in time we need to adapt
the system to be more scalable and
maintainable so
at this point we had quite a lot of bugs
regarding the transaction classification
some of them were wrong some of them
felt like there should be override by
another method and it came clear for the
business that this is important part
first of all customers keep complaining
about this
second of all it's like a base for all
the reports that we have so it has to be
right right
so when we understood it and they
understood it we could start a project
so we decided to give it a shot and try
to rewrite this part in order to make it
more stable but also more predictable
so
luckily also a few weeks before that
happened and I think that was also one
of the reasons there was new
classification method introduced like a
automatic one so I wrote some
exploration tests for that POC that
became a permanent solution
never happens right and the one thing is
that without tests this project will be
too risky and I think I wouldn't do that
I would start with the test anyway
um
those were integration tests and they're
really helpful because with the even
driven architecture well it's sometimes
unpredictable how the system will behave
if you put the events in different order
and uh
yeah right test why there was no test
for the POC why did I have to write that
I can tell you of the record but anyway
uh the project the project was about
respecting classification rules
so I told you we can classify
transaction right and then once we
classify one then the algorithm will
learn based on that knowledge and it
will automatically classify others of
them and so on and let's focus on three
classification methods so one is manual
classification this is the one that I
showed you the previous Slide the rule
classification is
it's based on the wording so you can say
that if transaction contains certain
wording then use this category and
automatic ones there's a couple of them
but they can learn either from your
account or other accounts and other
other stuff and then
as I told you they were spread around in
the code in multiple event handlers
and our project was to encapsulate those
business rules right we saw that there
is a lot of if statements some of them
looked very familiar and similar and
also sometimes it felt like the if
statement is missing in this and that
place and because of that we have many
bugs so
we decided to introduce an aggregate to
fully encapsulated this is how it looks
like there's a couple of methods I think
there's more race calls than other code
but this is how we decide to protect the
rules
by throwing in an exception
and as you can see once again it's very
simple Ruby object right it doesn't have
any external dependencies it doesn't
depend on the active record
should be easy to unit test right
because you don't interact with the
database
and once once it was developed with 100
of mutant coverage we felt like it's
good to start adding it into the current
process
and there is a test for that class so I
really hope this looks easy for you
because it's just a pleasure to write
such a test with the events based
assertions are definitely really simple
um but before we started using this
class in production we decided to extend
the existing test and once again
we use the streams for that and the
events in that stream so you can see
that this is the screen from actual git
log and here you can see that we added
just added some assertion that will
check if the correct events were
published
or stored actually in the event store
the next step is to pass those tests
right in order to do that well that's
simple we have to start writing to both
sources
and once again once we do that this code
is ready to go to the production but you
have to be aware that you should start
start the life cycle of the Aggregates
right or basically this right model in
order to do that you need to once again
backfill the data we use a pattern
called migration event
um and like it's really also good to
consider having like separate event that
is not normally used in the aggregate
because then you can actually see when
this migration had occurred
okay but then
we didn't stop here like with the bank
account because we decided that this
part of the system is too important to
have the same issues once again so we
really wanted to separate those two
concepts the read model and the right
model so we also decided to implement
the rich part almost like in this first
picture that I showed you with the cqrs
and
it was quite simple I thought it's going
to be harder this is just a simple event
handler like we did in the workshop that
listens to events and then based on that
updates the read model
the read model is just the old table
that we used to have is still there and
only actually two columns are now
considered the read model and you can
see that it's a very simple class you
could split it to four classes I guess
um
all it does it just updates the model
nothing else
yeah
Okay so
once we did that we deployed it to
production of course and shortly after
we got the slack notification that I was
really happy about
it says that there is an error saying
that we cannot override rule classified
transaction category with account
classification and as you remember from
the one of the previous slides the rule
classification is more important than
the automatic one right so it cannot
override it the automatic cannot
override the rule rule can override the
automatic
so it's basically this right right
manual is more important than rule it
can override it rule cannot operate the
manual and so on
so it seemed like it wasn't enough
and this is how we imagine the system
works so when the bank account send us
the bank accounts sync event and later
on there were three handlers that were
listening for that event and they were
processed doing some processing of the
data later on WE rebuilt the cash flow
models
those three cash flow models are the
same ones so this is how we imagine it
but that's like how how it looks like in
the reality
once again more I think this picture
says more uh about this so we talked to
a business
and we kind of wanted to know how this
thing should work in what order should
we
play those event handlers to get those
errors gone so we came up with this
solution that when the bank account sent
us the event
of course the sync one then we first
classified by rule because rule from the
automatic classifiers is highest in the
hierarchy then we use the account
classifier which is lower than rule but
it's higher than Global classifier and
once it's done we rebuild the cash flow
model once not three times
at the same time so
did we just discover a process
this is a very similar process to the
ones that we did at the workshop right
and
after we looked at the code and we saw
how the Aggregates are used how what
kind of Errors we get from production
this is kind of a breakthrough
it might not sound so exciting to you
because you don't work with me in this
domain but for us it was like oh finally
and once we understand that we notice
that there are three processes that we
had to implement
sorry for that
let's do it like we did today in the
workshop let's even Source those as well
so we can see that where the process is
hanging if it is on which stage it is
you can see how long each state takes
it's also really good for debugging and
troubleshooting
um also what's really cool about the
processes I hope that you saw that in
the workshop but if not then you have to
trust me that adding a new step is a
pleasure I actually showed you the
production code that we are using the
first process implementation and later
on right adding a free steps it wasn't
really hard and um this is how the bank
accounts aggregate looks like sorry the
transaction classification algorithm
looks like you can see that first I
classified it by account classification
then by rule and manually and those
results are solid it's not possible to
override for example the row classifier
with the account one and for the proof
you had the error on the previous slide
and this is how this stream of the
process looks like so we can see exactly
when it happened and how much time it
took well you cannot actually see that
but on the um on the right hand side we
have more columns normally I just cut it
so it's better visibility
and uh
to those who of you who were in the
workshop uh you already seen this but
this is how the code for the process
looks like so this is just a bunch of if
statements and first of course it builds
the state based on that state it knows
which Step should be now executed
of course there is the load method that
you can use which loads the events from
the Stream
then there is the apply method that well
in this case it just simple Flex it
applies the information on which step we
are
and later on there is a method to store
the process after it's completed and of
course the method to answer hey are we
done or not should I go for the with the
next step or not it also prevents you
from a situation when an event comes and
the process should be stopped so it's
not repeated twice
and this is how you test processes
in the async word so we did a little bit
differently in the workshop here we you
might not be familiar with the drain and
cyclic drop clear all but the the
processes in this project are
asynchronous and that's why we kind of
need to use this fake sidekick to be
able to test it
but in this case it's not a problem
because it's always ordered right events
May come out of order but they will not
be processed out of order
benefits
there are a couple of benefits both for
the dev team but also for the business
so when it comes to the business so
there is a possibility to learn about
our algorithm accuracy right because
consider following situation if the
customer
has Auto classified transaction
and then they change it manually by
manual classification
we can learn from that fact that hey our
algorithm didn't work well and we have
more learning data right we can just
extract this information from the events
business rules are encapsulated so no
mistake will go to the database yes the
user may see the error yes we may see
honey badger notifications but it will
not go to the database and all of you
who worked in production environment you
know how costly it is to
fix the data that is already in the
production in the database right
sometimes it just takes a lot of time to
figure out what to do with it should we
delete the record updated work hard
decisions so basically it saves us the
time and money because we don't have to
debug for so long
um
also
in this case
you saw that we implemented like almost
the full pattern there's only the second
database missing but we don't need that
and
we did it because the business told us
that this part is important and it has
to work
without any issues that's why we decided
to do that we started from a Crut right
we added some events on top of it
then we extracted and separated the
models we call it for now event driven
crowd hybrid All rights reserved
I think that's not a final name but
we'll see
um all right and this leads us to
another story and if you have a feeling
that the previous one it was complex to
implement then I won't fool you it
indeed consumes some glucose but
sometimes it's just way easier
than that
and a couple of months ago I grabbed the
ticket
and the business asked to get a feedback
from the user when they cancel
subscription
my first idea
let's just add a column into
subscription table
and save the data from the UI here
and I could do that but then I started
asking myself okay but what's next
what's the goal why do you need this
feedback I actually started discussing
with the business and I asked them
exactly the same questions and when we
were talking it just came clear that
you know we just want this data for now
so we're able to follow up on the
customers when they cancel subscription
maybe you can offer them something maybe
you can prolong it
a lot of things can be done if you have
information so
they ask what's the simplest can you do
slack notification
yeah
so it's just a notification of a
feedback
and after that I realized okay so I can
utilize the race events or
publish method which will both persist
the event in the event store and then it
will publish the event to the queue I
can simply make a Handler that will
fetch this event and then publish a
notification to Slack
really easy
and after that if they decide that yeah
but we would like to have a like grouped
feedback by some category or reason or
whatever yeah sure we can do that right
we have this information in events we
can always access that read a stream and
fetch that information but also what is
really cool is that
we can link this event to the tenant
stream
this is my test tenant so maybe there is
not so many exciting things but what you
can see is that what you can imagine
also is that if I cancel subscription
maybe I did it because of something that
I did previously maybe it didn't work
maybe I got bad report results
maybe something just blow up and I don't
like the application anymore right but
what is also interesting
is that you can track when people come
back
because you can also see when the
subscription is resumed and uh this will
be it's really funny because I just have
this thought right now that right now
we're launching a new campaign in which
we prolong every user's uh without
account sorry without active
subscription we give them additional
seven days to try out the application
because we introduce a new feature and
we want to see how many of them will
stay so this will help us calculate
which ones canceled and then which one
come back and we can also
uh on the timeline we can kind of align
it with it was the feature effect or
something else
I need to tell my friends from business
um and this is how the subscription
payload looks like right so this is the
feedback I told you about we have this
information right we can always come
back to that fetch it from the event
store and use this information and this
is the
slack notification that I used
really beautiful
um
but it's enough in this case there are
more important things to work on than
sending notifications beautiful
notifications
okay and so this is the end of my story
so now I have to admit something so
no they're not fake but a couple of
years ago
when I learned that there are more
important Concepts in programming than
latest JavaScript framework
such as secure stomach driven design
even driven architecture they got me I
really like them I bought the sales
pitch I saw a lot of value in them I'm
still exploring and seeing more and more
value but
I have I had this feeling that I need to
master all of them to start even
sourcing I don't know why maybe I read
the wrong books maybe I read the wrong
resources but even sourcing is just a
persistence pattern right we store an
information into an event store
so
I thought it's very hard and especially
I thought that I need to learn this
I need additional database I need to
learn how to manage an event store
maybe I need to vendor lock in but
and really scared me
besides that you know DDD I need to have
perfect class because then the streams
get too long and I need to deal with
snapshots and whatnot I need to do right
testing I need to know secure s
no you don't have to know that well
besides tests you better Master test or
I will Hound you but it doesn't have to
be hard and complex
interest you rely on well-known
components such as monolithical
architecture yes
and it's a 50 50 big ball of mud and
more or less
organized code we have a jobs you're all
familiar with jobs right we use sidekick
and there's single postgres database
driven by race event store so
nothing fancy right no micro Services no
kubernetes no whatever the buzzword is
so my message to you is that don't be
afraid of even sourcing
for me it turned out not to be that
complex actually it's the easiest one
from the patterns that I just mentioned
I really love combination of even
sourcing and even driven architecture
but
even driven architecture don't run can
be really hell and can break your
application so just use it wherever it
makes sense and be aware of that and
watch out for no order guarantee and if
you run into an order guarantee I have a
solution for you this blog post by Rapha
which is available somewhere here
it's really good it answers the question
how you can deal with those
so also when it comes to introducing
event sourcing as you hopefully so you
can do it gradually step by step and you
don't have to do that in Greenfield you
can do it in startup you can do it in
well sometimes which is a green field
but after you join after some time it's
not so green anymore you can also do
that in Legacy projects that everyone
hates and if you ask me that's the most
satisfying to work with
and as you saw once again sorry for
repeating myself so many times but we
started from krat introduced events
where it made sense right and once you
understood the business concept better
we went through with the patterns
sometimes we stopped we didn't Implement
all of them but sometimes it's just
worth it
it doesn't have to be perfect from the
start we need to adapt to the stage of
business we are in and then we need to
improve and improve
event-driven hybrid crud it's a thing or
rights reserved and remember even
sourcing DDD like none of those patterns
I uh addressed are their notes silver
bullets
like every every pattern has its meaning
and its purpose
they won't solve every problem and you
have to watch out because there are
traps
thank you that will be all
foreign
[Applause]