Hacker News new | ask | show | jobs
by hn_throwaway_99 2053 days ago
I think the issue really is that when people talk about CQRS they are almost always talking about event sourcing + CQRS, and that's where the complexity lies.

I mean, look at GraphQL, which essentially makes it trivial to implement "plain" CQRS because there are always explicitly separate operations for mutations and queries, and it's easy to have separate object definitions for these operations (this is in direct contrast to many REST architectures, where your verbs - GET, PUT, POST, DELETE, etc. - are fundamentally operating on the same objects). However, underlying in the actual DB there is just a single representation.

But I think when people talk about CQRS these days they are really talking about the underlying data being different (e.g. a log of write operations vs a repository of queryable objects), and that usually implies something like event sourcing, and with that model you have a ton of complexity involved in keeping the different "sides" in sync, and since many update operations also involve queries (i.e. only do this update if something else is true about another object) you get into transactional difficulties as well.

1 comments

Correct, this is what I meant. Even though they're technically different concepts, I've found in practice they're almost always coupled together.

FWIW, these days I usually do go with GraphQL over REST in my APIs, partially due to some of the advantages you get from separating the queries and mutations. But like you said, I prefer to ultimately store the info in a DB in one consistent format unless it's absolutely unavoidable. Sometimes it is unavoidable, but like the article mentions you can frequently get away with having a "Reporting Database" separate to your "Primary data" database.

Once you start spreading your data across multiple databases and storing it in different structures managed by different apps with different APIs, suddenly getting to even eventual consistency can quickly become a non-trivial problem, which itself is usually solved or mitigated by adding more complexity.

Sometimes this complexity really is required because of incredibly large scale, large/numerous engineering teams working on one project, or unique business requirements - but my original point was that for most cases, particularly new products/projects that aren't going to have 10M+ daily users from launch, you should keep it simple until you know for a fact that it needs the complexity of a full CQRS + event sourcing system.

> Even though they're technically different concepts, I've found in practice they're almost always coupled together.

Not really. Event sourcing is typically implemented with CQRS, mainly due to how ES relies on streams of command messages and as CAP-related requirements already require mutable and immutable commands to be processed differently. However, CQRS has zero requirements other than segregating interfaces.

Hell, in languages like C++ you already get CQRS out-of the-box by following const-correctness.