4 ms·
I've worked with event sourced systems quite a bit in production and at scale, and have written a book on Akka and another one on related topics. While I have b
by ninjakeyboard 8y ago
I've worked with event sourced systems quite a bit in production and at scale, and have written a book on Akka and another one on related topics. While I have been an advocate of the approach, My experiences are guiding me away from implementing Event Sourcing in many use cases (especially where the entities are long lived). While CQRS is more complex, I'm more likely to implement CQRS without event sourcing, where an entity is responsible for its own persistence using whatever mechanism we deem suitable, and emits events that can be used for the view (or the data can be viewed as read only.) Ultimately a bounded context is there, and you send it commands and get out events. You have to evaluate the recovery and persistence mechanism based on your needs. Exactly once delivery is a pipedream so it doesn't matter how you're persisting the event and delivering it, evaluating line by line, crashing somewhere it's going to be possible to emit an event twice somewhere (eg if the outbound projection emits the event but doesn't persist its offset.) You need to deduplicate somewhere to get exactly once processing semantics. There _are_ simpler approaches to persistence that work just fine with the same delivery guarantees that work fine in the place of Event Sourcing. Nobody talks about any alternatives though - everyone defaults to event sourcing. My intuition guides me to look at other options having been burned one too many times, watching organizations collapse around 100% event sourced applications, etc.
I'm still working on event/message driven systems (today with Elixir mostly) but I've started to make architectural compromises to move away from especially event sourcing. Event Sourcing + CQRS may be prescriptive but it's very hard for new developers to pick up and understand the layers of abstraction underneath eg Akka + the Persistence Journal. And I'm not sure I can trust many of the open source libraries outside of Akka to be honest. I've had to dig into the depths of postgres journal implementations and apply windowing to journal queries for example because they weren't burned in at the scale I was working with (partially because I inherited an application with a single entity in a context which had many million line long journals - this highlights a design error though but hopefully you can see my point.)
You don't _need_ to use these patterns but you can still apply DDD and event/message based abstractions, and publish events. An entity can write its state to a record and then apply the state in memory as well without using a journal given you handle exactly once processing semantics correctly. This means there are knobs and dials. The problem with event sourcing in the greater picture is that it's descriptive of an approach, and there aren't many clear alternatives that people are talking about that work in similar system designs. If you have very long lived entities, or only a few of them, it gets especially difficult to keep the system alive over time, but for those use cases it doesn't mean you should stop receiving commands and emitting events.
You always here about the idea of the approach, never the reality of maintaining these systems, or the inappropriate use. In one implementation, there is one entity that receives thousands of events a day, and lives forever. How do you maintain the journal while changing the code, keep it alive over time? I've watched event sourcing and CQRS sink projects and teams. I've watched well paid contractors unable to figure out how to cluster and scale these systems. The barrier to entry for people to become effective can be high and you should understand the long view in terms of people required and cost over time and validate the approach for your use case very carefully. Again, the fact that everyone talks about event sourcing and no closely related alternatives makes it seem like the gold standard or the only option but there are other (simpler) ways to deal with your persistence in an overall similar architectural approach.
- raarts 8y agoI've re-read your post a couple of times, but still find it confusing. It reads like you're an early-adopter, and got burnt multiple times by design flaws, and people not being familiar with it. Suppose ES/CQRS is designed well, and a well-understood mechanism, would you still move away from it? For which scenarios? I can imagine exactly-once delivery not being a problem in all scenarios. And what is the problem with long-lived entities? Solely the fact it takes longer to reconstruct current state?
- marcosdumay 8y agoThe GP sounds exactly like the "you don't need microservices for everything, you can have well built monoliths too", "not everything must be a single page app", or "not every datacenter should be replaced with a cloud one". ES specifically has a large list of drawbacks, so not everybody should use it. It would be great if people could tell about how there are many changes of gray between "CRUD-only we forget everything that is not current" and ES, but in a hush to make a point people act like those are the only known possibilities.
- ninjakeyboard 8y agoI'm only saying it isn't the only approach, even if you're keeping the source of truth in memory. It's the most prescriptive approach for sure so is the one people tend to go for first but there be dragons in managing especially long lived journals. Migrating the journal over time, figuring out how to truncate it (especially if there is an initial creation command/event that describes the rest of the life, or periodic updates to the structure - you have to keep all of that data forever potentially to know that it's going to wind up being correct.) And yes long recovery times are an issue unless you want to keep every entity in memory forever and ever, or you can tolerate extremely slow turnaround times. There are knobs and dials here that are subtleties that people won't think about until after they launch. If you have a hammer everything looks like a nail kind of thing. There are other ways to handle problems that are only marginally different in how they persist and recover state, yet are far more usable for certain use cases. I'm extremely skeptical when I see someone gung-ho for event sourcing if they've never used it though. I tend to look at the problem very hard to see what else we could do for persistence while still maintaining the "source of truth" in memory.