How to get state of an aggregate in CQRS pattern?

According the article of Martin Fowler and Microsoft CQRS Journey , the CQRS is a pattern applying in a BC, not the architecture for whole system. I get confused in how to get state of an aggregate from anything external in CQRS.

Should an aggregate have a command Get to return its state in write model, or a corresponding query in read model?

It’s example of shopping cart service in Akka Platform Guide.

ShoppingCart is an aggregate, it has three commands: AddItem , Checkout and Get . In the command handler of Get , it replies summary of shopping cart to the command sender. In this way, each aggregate has a command Get to return its state in write model.

But I suppose the Get is a query exactly, not a command. Because in CQRS pattern, command changes the state of the aggregate and triggers events, but returns nothing. On the other side, query returns a copy of the current state of the aggregate, but changes nothing. All commands exist in write model, all queries exist in read model. If I want to get state, I shouldn’t send a command to write model but a query to read model. The eventually consistence is maintained by the event projection from write model to read model.

So, the Get of ShoppingCart should be moved into read model. Anything external wants to get the state of ShoppingCart , it should send query Get to ShoppingCart and get reply Summary finally. But in this way, the state maybe is stale. Should it get problem in consistence?

Which design is necessary and better?

Putting Get in read model gets risk of consistence, putting it in write model gets semantic ambiguity otherwise. That’s my confusion.

Thanks.

Hi @Casperlet ,

I think you have a good understanding of the trade-offs. In the Shopping Cart we demonstrate the Get command on the write-side for multiple reasons:

  1. show the feature of handling a command that produces no events
  2. exemplify that sometimes consistency is required and that’s possible within the scope of a single aggregate

Cheers

So that’s it, I see. I get misleading for this example. :stuck_out_tongue:

And I will prefer to group all query operations into the read side. That’s the pure CQRS pattern what I understand.

If possible, would you mind to add a comment about this into the preface of the guide?

Thanks.

Another pro with not handling queries in the aggregate is you can keep the state focused on only what’s necessary to support the command -> event flow. The state of the aggregate does in no way need to look like the projected read model(s).

@PerWiklander, I totally agree with you on this and that’s how I would do as well.

On the other hand, when building a library we can try to block some patterns and try to be purist or we can let the users decide if they want to be purist or not. I think the later is a better option even if I would choose the purist path myself.

Since we are building it on top of an Actor Behavior we can’t block the users from replying with whatever they want. Otherwise we would need to build an API that hides the Actor API and that’s not great.

And we would have to always return void/Unit or Done, but never T because T would allow the user to return anything they want, including the state.

Anyway, I just want to give some more context on why we allow it. I hope this clarifies.

Cheers,

Renato

Yes, I agree on this point. Keeping the write-side enclosed is very important for an aggregate.

It’s the rule that never offer a free style query interface to users, just like accepting a SQL string as parameter, but specification style with method isSatisfied(condition).

It’s the rule that never offer a free style query interface to users, just like accepting a SQL string as parameter, but specification style with method isSatisfied(condition) .

That’s not something you could do in Akka. The persistence infrastructure is completely abstracted away in the write-side. The only thing you could ever do is to return the current in-memory state of the aggregate. You could indeed send queries that respond based on the current state.

The consistency of the aggregate is protected. It can only be modified by applying events.

I’m VERY happy with Lagom’s move towards pure Akka, so that the user can decide. Implementation choices such as the one I described should be encouraged in documentation and tutorials, not enforced in the API.

It’s always hard to make a simplified “hello world” that at the same time needs to explore as much as possible of the API. These often trick new users into thinking that this is The Way™ to develop complex systems.

1 Like