I'm always excited to see posts about CQRS and Event Sourcing. My current project is entirely ES/CQRS-driven and it's been a revelatory experience. I can't understate it. As Charity Majors says:
> And while storing raw events may be "expensive" compared to any single optimization, all optimizations can be derived from raw events.
> The reverse is impossible.[0]
But I have to say: the resources that this site links only served to confuse me. Greg Young may have popularized these concepts, but watching his talks left me with little practical implementation guidance, and Udi Dahan was even worse, much, much worse, in terms of leaving me helpless and confused.
What really helped me was "Designing Event Driven Systems"[1] a promotional book by Confluent that nevertheless has many great sections with practical advise for implementing these patterns. Likewise the CQRS/ES FAQ[2].
And while this post says you don't need Kafka for CQRS/ES, Kafka sure does help. Kafka Streams is the ultimate tool for CQRS/ES. It contains all the primitives you need to do CQRS/ES easily. I am in the process of writing a blog post about my experience and am looking forward to sharing it. People love React/Redux, state as a function of reducers, and time travel debugging on the front-end: there is no reason you can't have all the way down your stack. Kafka Streams makes this possible, and much easier than you'd think.
I agree, the Confluent team paint a very clear big picture. You may be interested to take a look at Crux [0], a general purpose document database with bitemporal graph queries, implemented as an ES/CQRS system directly on top of Kafka (or a local KV store).
We created Crux because we found ourselves routinely needing bitemporal functionality when building immutable systems that are capable of ingesting and interpreting out-of-order/late-arriving events [1].
So far we have decided against using Kafka Streams to keep our log-storage options very pluggable, but we pretty much implement the same mechanics.
Thank you! I look forward to checking this out. I'd say the picture painted by Confluent is much rosier than reality, but it definitely is the clearest, most actionable picture to date.
To be specific, the picture I am thinking about in particular is described in a slide titled "Local consistency points in the absence of Global Consistency" (from this talk: https://youtu.be/VYOMmwkdSig?t=1817), where it shows how each local consistency point is ideally implemented using ES/CQRS. I also agree that the tools Confluent are currently providing us with today do not make this trivial.
Edit: the other big picture Confluent quote I like is "You are not building microservices, you are building an inside-out database" (Tim Berglund, Confluent, 2018) which is a perfect answer to this other quote: "The hardest part of microservices is your data" (Christian Posta, Red Hat, 2017)
We use CQRS and event sourcing for most of our backend services at my current employer (https://m1finance.com); it's generally been a good experience, but we've learned a lot along the way.
My thoughts on the process are:
1. Being able to use a pure/functional event-driven model for the command model, and a standard relational model for queries, is the big payoff for us; we get the best of both worlds.
2. Our model does not encapsulate command-side and query-side updates in a single transaction, nor does it require
that they live in the same database; this gives us a lot of benefits for scalability, but it introduces eventual consistency, and not having "read-your-writes" consistency can make things harder for our front-end devs.
A simpler model that does transaction updates to both side might be a win for a lot of teams, and I still wonder if we should have gone that way.
3. We use Kafka for bulk dataflow and inter-service messaging, but not as the internal event store; that gives us some leeway for migrations and surgical edits to the event stream where necessary.
We've found that Kafka's immutability and retention properties do not make it a good fit for a primary source of truth; it's way too easy to "poison" a topic with a single bad message.
4. One thing that none of the books/frameworks do a good job talking about is external side effects with vendors/partners/legacy systems. That's definitely been the single hardest part of our implementation, and we're still evolving our patterns here.
Overall, though, it's been a great direction for us, and we're excited to keep pushing our architecture forward.
> And while storing raw events may be "expensive" compared to any single optimization, all optimizations can be derived from raw events.
> The reverse is impossible.[0]
But I have to say: the resources that this site links only served to confuse me. Greg Young may have popularized these concepts, but watching his talks left me with little practical implementation guidance, and Udi Dahan was even worse, much, much worse, in terms of leaving me helpless and confused.
What really helped me was "Designing Event Driven Systems"[1] a promotional book by Confluent that nevertheless has many great sections with practical advise for implementing these patterns. Likewise the CQRS/ES FAQ[2].
And while this post says you don't need Kafka for CQRS/ES, Kafka sure does help. Kafka Streams is the ultimate tool for CQRS/ES. It contains all the primitives you need to do CQRS/ES easily. I am in the process of writing a blog post about my experience and am looking forward to sharing it. People love React/Redux, state as a function of reducers, and time travel debugging on the front-end: there is no reason you can't have all the way down your stack. Kafka Streams makes this possible, and much easier than you'd think.
[0]: https://twitter.com/mipsytipsy/status/1115537408705957888
[1]: https://www.confluent.io/designing-event-driven-systems
[2]: https://cqrs.nu/Faq