Why not ES and CQRS? Seem like I should be scared but don't understand why

484 views
Skip to first unread message

Morten Høgholm Pedersen

unread,
Oct 23, 2017, 8:06:04 AM10/23/17
to DDD/CQRS
I am working on an enterprise data management system - and about to settle on main technologies to use and initial architecture. The system is to collect most of the business critical data for a company and it is important to be able to ensure that all data is captured, correct and not tampered with (by accident, ignorance or at will). I have read and studied as much as I could about ES and CQRS and find the model(s) very attractive and making a lot of sense. 

I wonder, though, why there are so many "warnings" and discussions of when not to use it. Martin Fowler also states there are a lot of cases, where it should not be used, although not really specifying which and especially: why. I simply do not understand where and why that is the case. The CQRS and storing all (relevant) events in a long log makes so much sense if you need to be able to prove why the current state is as it is and I have a hard time seeing why it should be overly complicated (maybe because I have never built such a system yet :-) ).

But if you have a CRUD system, you do get some kind of "command" from the application, that asks the database to update a specific item, and you get an acknowledgement, so you know it is OK to update the UI with the new value. What is the real difference, except losing the trail of what happened in the CRUD system unless you also store correct and detailed audit logs. In the CQRS / ES system, you also get a command from the US, send the event to the event store and the event is messaged to a projection that updates the item, which is then reflected in the UI as written. Is it a longer and more complicated way? In essence there is not much difference I think - except for storing the exact event instead of an artificial audit log. If you use a big hairy database for the event store, and a big message broker to pass it on to a big logic service that in turn updates the SQL database(s). Yes the path is longer - but is that necessary unless you have a very big system? At which point the CRUD system has also grown very big.

Can anybody help with more information on implementations, experiences and details of using CQRS and ES or not? It would be great if there were some examples that was not the only two I've seen (social network sites and banking examples) and maybe if there are some information on implementing this on small (small single problem solution), medium (typical company internal solution) and big scale (big enterprise solution) it would be really great. 

I think it is a bit hard to bridge the gap between the very simple examples and implementations, that suddenly seems huge, although they should not be conceptually harder to understand.

kind regards and thanks in advance
Morten

Morten Høgholm Pedersen

unread,
Oct 25, 2017, 8:05:08 AM10/25/17
to DDD/CQRS
Any way to get some opinions here?

Peter Hageus

unread,
Oct 25, 2017, 8:45:58 AM10/25/17
to ddd...@googlegroups.com
It’s a very broad question, that ultimately comes down to the classic ‘it depends’.

Some of the challenges I’ve come across applying CQRS/ES:

It takes a while to get the infrastructure right. Once you do, a lot of things fall into place. (suggestion: Start with EventStore, it steers you in the right direction)

Eventual consistency is usually not a big problem, but when it is you should be aware of the patterns to handle it.

There are more moving parts, monitoring is essential. 

Some developers just don’t get it. (My worst case was an older guy who’d only worked with MS tools for his entire career. It never clicked for him)

If there is no behaviour to a piece of data, it’s a very roundabout way to model it using events with proper granularity. OTH, when there is complex behaviour it’s so much easier…

/Peter



--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
Visit this group at https://groups.google.com/group/dddcqrs.
For more options, visit https://groups.google.com/d/optout.

Danil Suits

unread,
Oct 25, 2017, 9:15:12 AM10/25/17
to DDD/CQRS
I have read and studied as much as I could about ES and CQRS and find the model(s) very attractive and making a lot of sense.

Me too.

I wonder, though, why there are so many "warnings" and discussions of when not to use it.

I was doing some reading last night, and came across this comment by Scott Bellware:

The difference between what is being called "traditional" architecture here and event sourcing is in which things that have to be correct from the very start. I.e.: The things that you can change later in traditional vs event-sourced are different. If you don't know realize that this is the case, and proceed with developing an event-sourced system, you'll end up facing decisions that you'd expected to be able to reverse later which are not reversible.

I, personally, can't speak to those differences in great detail, but I think that Greg's book on message versioning points to one of them: if your book of record is messages, then knowing the state of things now requires being able to interpret messages from the past, so you better have taken time in the past to think about how you are going to read messages in the future.

Cache invalidation might be another; if you don't want your users to be confused by the fact that the view that they are looking at now is older (more out of date) then the one they were looking at a moment ago, you are going to need to do some thinking on how to manage that.

In addition, I think Udi Dahan raised a really good point

Who put you in a position to decide that development time and resources should be diverted from short-term business-value-adding features to support a non-functional requirement that the business didn’t ask for?

 

Danil

Morten Høgholm Pedersen

unread,
Oct 25, 2017, 9:16:09 AM10/25/17
to DDD/CQRS
Thanks - yes - broad question, but I had a hard time nailing down exactly what the "question" since the stuff I researched on it all seems to point me in the direction, that it makes sense. What I've seen in some presentations and experienced when discussing this, is that very often people seem to "fall back" on the CRUD way of doing things and starts to model the system as they are used to and I suspect that is why people land hard between two chairs. E.g. when the discussions start on how to "update" the event store when new versions of the system is rolled out (where the whole point is, that it should not be updated - unless you at some point get way to complicated logic to handle old event formats)

Well I think my concern was / is that the concept of CQRS and an event sourced system clicked instantly when I heard / read about it first time and therefore I'm just trying to ensure I am not too enthusiastic about it :-) I'll take a deeper dive into EventStore then, which was on my list of candiates for storing events (as Kafka or more traditional databases).

Thanks for your input Peter.

Kijana Woodard

unread,
Oct 25, 2017, 10:15:32 AM10/25/17
to ddd...@googlegroups.com
To follow on Danil's point...

When I took Jimmy Boagard's excellent nServiceBus class, one point stuck out. With messages, you're compelled to think about boundaries, transitions, forward and backward compatibility, SLAs, and failure scenarios. With crud, those things are often opaque to you and not considering them doesn't stop you from making progress. With messages, alarm bells are going off in your head constantly.

That's "good" in the sense that you feel much more comfortable getting into bed after release day. You've already put things in place to handle bad things together. You don't have that lurking fear that your house of cards will come tumbling down.

It's "bad" that all that consideration takes time. You could have just slapped together some ddl, bootstrapped in some reference data and scaffold out some forms. 

Now, some kind of changes are great under ES. Oh, here's a bug in our projection, fix it and start over from the beginning of time. Oh, here's some new way to look at the data. No problem.

Some things are easy with crud. Oh we need to change every Foo to be X. Update statement and move on. With ES you're doing a code, test, deploy.

But just on the upfront thought work necessary, if you strip it down past all the rationale and explanations, it resolves to a simple question. Do you want to pay now or pay later? For most people, the answer is pay later.

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Morten H Pedersen

unread,
Oct 25, 2017, 11:47:58 AM10/25/17
to ddd...@googlegroups.com

Hoegge

unread,
Oct 26, 2017, 2:50:17 AM10/26/17
to DDD/CQRS
I tend to not agree that this is a good point:

In addition, I think Udi Dahan raised a really good point

Who put you in a position to decide that development time and resources should be diverted from short-term business-value-adding features to support a non-functional requirement that the business didn’t ask for?

Developers need to decide on non-functional requirements all the time - otherwise the business people would not need them. Just looking at short-term busines-value-adding feature creates a lot of technical debt over time. It is almost as asking a doctor to only do the treatment the patient asks for. Fortunately, I have been put in the position Udi asks about ;-)

Kijana Woodard

unread,
Oct 26, 2017, 10:08:57 AM10/26/17
to ddd...@googlegroups.com
Exactly.

To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/utDBHOissxI/unsubscribe.

To unsubscribe from this group and all its topics, send an email to dddcqrs+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+unsubscribe@googlegroups.com.

Kijana Woodard

unread,
Oct 26, 2017, 10:09:52 AM10/26/17
to ddd...@googlegroups.com
Then we should sell the rest of the organization on the benefits of our non-functional requirements. It's a bad idea to simply foist costs upon an unwilling organization and assume they'll like the benefits at a later date.

--

Denny Crane

unread,
Dec 25, 2017, 3:20:03 PM12/25/17
to DDD/CQRS
There's good input from others here; here's my experience with it:

TL;DR -- Don't use it unless you have something to gain from it. While it offers a cleaner, scalable design methodology, it comes with a lot of complications that require the adoption of a number of practices that will likely be foreign to many if not most of your developers.

We are using ES and CQRS and we've had pretty good luck with it, save some boxing with the infrastructure details. CQRS and ES are two completely different topics, but they have a strong synergy which each other.

I think the biggest point I'd make is that EventStore isn't just a technology that you can drop in. There's an entire practice behind it. The way you think about objects and such has to change drastically from traditional approaches, and you'll certainly want to write a number of abstractions around it. I also found it almost necessary to adapt some level of DDD in order for it to make sense. You don't have to do it, but I found that it's harder to reason about if you don't. The two practices have a lot of shared concepts.

CQRS isn't just an application architecture you can drop in either. Again, there's a whole practice behind it.

So in my experience, I feel like a big reason it is stated that there are times you should and should not use it (without much support for the statement) is to guard against backlash from the development community in response to the complexity that it introduces, but there are some pretty obvious scenarios where you shouldn't use it -- basically when there's no gain from it. That said, I always argue that the complexity is front-loaded. It's very different from what the vast majority of developers are comfortable with and will grate on people's patience pretty harshly.

When I got my team started on it for our new platform, I told them up front:

"Look, I chose this practice to solve a handful of real problems and it's a long term strategy and there will be a handful of places where we don't use it. Just understand right now that you're going to have to unlearn a lot of what you have learned up until this point, so adjust your attitude towards this accordingly. It's the same language, but your design experience is about to be turned upside down."

I got a range of concerned and confused looks, and even some eager-to-learn-something-new-and-break-the-monotony looks, but I set the expectation. I followed up with a long discussion about those problems I mentioned and a very high level explanation about how a lot of those things will be solved with the new design methodology. I focused on the fact that no one thing was going to solve these problems, but the architecture/design as a whole would put a pretty significant dent in it and that in the long run, and developing the software would actually get significantly easier than it would have been without it. I had to let the team argue about it for many hours over a couple days, listing out the drawbacks and extra work that would need to be done, but by the end, everyone was bought into at least giving it a go.

It took a couple months of tough times for it to click with the team, but they eventually saw exactly what I was talking about. The biggest challenge for me was being a champion for the design. I had to understand it very well. I had to either have an answer for every question or at least understand enough to discover it with the team. That meant lots of a reading, proofing, and second guessing my understanding (I'm still doing that). 

So to sum that up: the hardest part of making the switch is getting everyone on board. 

As far as technical considerations...

I found that it was merely a question of whether or not eventual consistency was ok for whichever service you're about to stand up. This led us to acknowledging that a microservice architecture may lend better to this approach and place us in a much better position going forward anyway. So we started with coarse grained SOA and eventually broke things down to microservices, but that's a different discussion. 

My rule of thumb for our system was that, unless that particular service absolutely needed immediate consistency, it would likely be event sourced in a CQRS model. Domain services (I mean to say, services that focused on some vital part of the business practice vs. 'domain services' that are in the actual host process itself) were all done as CQRS because we basically have no need for immediate consistency. There were exceptions like super focused services (microservices, really) like ingestion services. Those would be pretty monolithic which is ok because they were tiny. 


In the CQRS / ES system, you also get a command from the US, send the event to the event store and the event is messaged to a projection that updates the item, which is then reflected in the UI as written. Is it a longer and more complicated way? In essence there is not much difference I think - except for storing the exact event instead of an artificial audit log

Ehhh... no they're not quite the same. Command models are typically written in an async messaging architecture (i.e. against a Service Bus) so you have some complication around that. A lot of "trust" really. So for example, your UI would tell the API to do the thing, then the API would drop a command on the bus to do the thing, but that is done asynchronously so your API returns 202 Accepted and your UI only knows that the command was issued, but it doesn't know if it was actually executed, so you have a couple options. 

- You can either trust that the 202 means that the command will be eventually executed and that any errors will be reported back at some point
- For "insert" type operations, you could have the API (or the client, to be honest) generate the ID and then queue the command and return OK with a location header pointing to where the resource will be once it's created, then poll that resource until status != 404 before displaying a success. This isn't uncommon, but I find it a bit kludgy.
- You can have the API issue the command and then subscribe to a response queue and hold the connection open with the client until it gets the response. There are frameworks that abstract this process. We use NServiceBus which offers message callbacks. Pretty straight forward.

You'll run into stuff like that. You *could* write the application in a synchronous fashion, but I think you'd be creating new bottlenecks in the system. CQRS shines in an asynchronous model where data is basically always in flight, but it's a bit more complicated and that's what turns some people off of it.

If you use a big hairy database for the event store, and a big message broker to pass it on to a big logic service that in turn updates the SQL database(s). Yes the path is longer - but is that necessary unless you have a very big system? At which point the CRUD system has also grown very big.

Large systems tend to operate this way anyway unless immediate consistency is required. I usually try to make every case I can to disprove the need for immediate consistency. Many developers claim that it is needed simply because it fits their typical design approach (request-response-request). Those systems don't scale particularly well which makes them really expensive since you end up dumping more money into developing the data tier both in terms of design, infrastructure, and hiring the people to each. In the end, though, you're still going to have one or more stores that get very big. In fact, you'll probably have at least twice as much data because now you have events in the ES AND projected data in a database.

In our CQRS systems, the domain operates off of the EventStore. This replaces the OLTP database; the ES becomes the source of truth for the domain. That data gets picked up and projected by the Query model and can end up in one or more databases. We ditched SQL and started using MongoDB for the query model. Development goes much faster. We also have some projections that push data to specialized databases such as ElasticSearch and Neo4j. We're looking at revising this approach to fit in with the data pipeline. But in essence, the application layer is Service+ES+ProjectionStore and then your data pipeline will move data from the projection store into a data warehouse and any downstream data marts just like you would in any other traditional model. I feel like it would be ideal to eliminate as much of the projection store as you can in lieu of the data warehouse, but I'm still churning on that. EventStore (geteventstore.com) has a built in projection mechanism so you could potentially eliminate that denormalization process from your query model and instead, build your ETL process to pull those projections straight from ES and place them in the data warehouse. Then your Query model can just get its data from there. It's a thought... not sure how viable.... anyway...

So going back to the warnings of not choosing CQRS+ES for every project. If your project (or a service of the project) is purely CRUD, then I wouldn't recommend CQRS+ES. It's a lot of effort for not much gain, so just stick to the traditional service model. 

It helps to redefine what you understand as CRUD. To me, CRUD is a system for updating records. You either insert a new record, find a record and change something about it, retrieve it, or delete it. I look at this like a file system and almost any system can be made to fit this mentality. I use this model for things like data ingestion systems or financial transactions. When I consider CQRS+ES, I think they fit better with *PROCESS*. So for example, 

1. I have a service that has a lot of business rules like generating surveys based on data collected from an ingestion service -- then I start thinking CQRS. Particularly CQRS using DDD in the command model.
2. If the process could have several people in there working with the same data, like a booking system, then I DEFINITELY consider CQRS and absolutely using DDD in the command model.
3. If the service is performing a workflow and can be run in the background, I choose CQRS+ES+DDD and utilize Sagas to orchestrate them.

It is a matter of preference that I use CQRS+ES for scenario #1 for all domain-centric services. I don't have to do it, but in my experience, once everyone is comfortable with it, the design and implementation of new features tend to go faster in that application model. 
Reply all
Reply to author
Forward
0 new messages