What are the problems with command handlers returning data in CQRS

cqrsevent-sourcingeventual-consistency

I have a system using CQRS/ES, where:

  • The command handlers are actually implemented as an application service layer, which executes synchronously. I.e. events are persisted in the event store before the application service layer returns.
  • The read model is not required to be updated synchronously.

My implementation departs from typical CQRS/ES, in that:

  • the aggregates actually do expose some state via read-only properties;
  • the command handlers (application services) return the aggregate, and my web API is able to return updated state in its responses;

This allows the client to update its representation of the affected resources, without having to perform a follow up query immediately (which possibly would return data from the out-of-date read model, since read models can be updated asynchronously).

This approach appears to be frowned upon, given that most of the literature says that command handlers should not return domain data.

What are the drawbacks of this approach, and is it an acceptable way to avoid post-command queries, and dealing with the eventual consistency of the read model?

Best Answer

CQRS is a principle, not a dogma. Like all principles, it has its positive and negative aspects in its own right. Departing from "pure CQRS" could just mean that you can't meaningfully call it CQRS.

Quoting Martin Fowler:

The really valuable idea in this principle is that it's extremely handy if you can clearly separate methods that change state from those that don't. This is because you can use queries in many situations with much more confidence, introducing them anywhere, changing their order.

In other words, queries crafted this way are idempotent, and therefore provide the same benefits as any other idempotent or "pure" method. cf. functional programming.

Like all techniques, it has a cost:

Despite these benefits, you should be very cautious about using CQRS. Many information systems fit well with the notion of an information base that is updated in the same way that it's read, adding CQRS to such a system can add significant complexity. I've certainly seen cases where it's made a significant drag on productivity, adding an unwarranted amount of risk to the project, even in the hands of a capable team.

The questions you need to ask yourself are these: do you need these benefits or not? And are the benefits worth the additional cost?

Fowler discusses the benefits and pitfalls of CQRS in detail here and here.

Related Topic