Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD and CQRS: use multiple repositories from a single command handler?

A canonical example of a simple e-shop.

Let's say a user adds some items to a basket and clicks "Checkout". A "Create Order" command gets issued. Now, before actually creating an order record with status "Payment Expected" and corresponding order lines in a db, we have to check that the items that the user selected are still available (maybe some items were available when the user added them to the basket but not anymore). And we also have to reserve them, so that they do not suddenly disappear while the user is still checking out.

So my question is how to perform this "check and reserve" routine? The way I see it I have multiple options:

  • In the "Create Order" command handler use ProductStockRepository to reserve the products and then on success use OrderRepository to create an order. Meaning, we use multiple repositories in a single handler.
  • Do not use ProductStockRepository in the "Create Order" handler directly, instead, create a ProductStockService and invoke methods on it to check and reserve the products. We still use multiple repositories in a single handler, but the usage of the stock repository is abstracted.
  • Create an internal "Reserve Products" command and dispatch and await it from inside the "Create Order" command handler.
  • "Checkout" button sends a "Reserve Products" command instead of "Create Order". In the "Reserve Products" handler we try to reserve the products and on success invoke a "Products Reserved" domain event. A corresponding event handler fires, in which we create an order.
  • Some other way?

This is not a question about how to best model an e-shop checkout flow. The above is just an example. I would imagine there could be many similar scenarios in many different applications.

like image 375
CKK Avatar asked Oct 31 '25 14:10

CKK


1 Answers

The solution to the problem you present is not a matter of coding "style" or following good DDD practices. If using multiple repositories in a single handler solved your problem, I believe you should consider it a good option.

But the main issue in this type of scenario is that in many systems, Orders and Stock are in different Services/Bounded Contexts, therefore in different databases. Stock could even be in an external system not controlled by you. This means that you can't reserve the stock and place the order transactionally, so you risk reserving the stock and not placing the order or the other way around.

The reason why using events is recommended to handle these scenarios is because with events it is possible to develop this type of workflow reliably although this introduces new complexities. With a bit of technology, it is possible to reliably reserve the stock and publish an event and on the other side, reliably capture the payment and publish another event, then place the order and publish another event, etc. This workflow can involve things like outbox pattern, retries, sagas, compensating actions (to rollback the previous steps in case one step fails), etc.

like image 68
Francesc Castells Avatar answered Nov 02 '25 12:11

Francesc Castells