Let's say we have a simple food delivery app. Where client order the food, then restaurant start preparing the food and gives it to the courier who delivery it to the client.
So here we have three different domains and each of this domain have their own order:
client - here client order the food and have the status of the food in preparation | in delivery | delivered
restaurant - here restaurant got its order and has their own status in queue | in preparation | ready to pick up
courier - courier has only two status delivering | delivered
Moreover each of this domain has their own price and other attribute about order:
client - total price (food price + delivery cost + fee)
restaurant - price of food, time of production to give a hind to the client when food will be delivery
courier - cost of delivery
All I want to highlight is that each of the domain has its own order aggregate, so according to DDD
we have to keep it in different aggregates even in different microservices:
/orders/:id
provides the general status of the order and total price to the client./restaurants/:restaurantId/orders/:id
provides the status of the food in restaurant domain and cost./couriers/:courierId/orders/:id
provides information how much courier earn from this order and how long it took to delivierBut now I met another problem, because client order combines information from other domains (is food still in restaurant or it's being delivery) so I have to gather this information when client asks about its order, but it means that client doesn't have its domain (its own aggregate, total price, discount etc), but if I create order aggregate for the client then I will not keep all information about order in one place (when restaurant give the food to the courier it should also change status of the order in client domain) what is not really according to microservices, because we keep information about the same order in different microservices.
Should I just create one order domain or should I split it to different domain and make these domains communicate between, when something will change in one domain?
One useful approach is to leverage domain events. When the restaurant's view of the state of the order changes, an event describing that change is published. The other services can then update their model of the event (assuming that that change is relevant to that service).
So for instance, we might have:
OrderCreated
event emittedOrderCreated
event, translates the order for the restaurant (e.g. uses the prices which the delivery app pays the restaurant vs. the prices the delivery app charges the user) => OrderSentToRestaurant
event emittedOrderCreated
and begins trying to figure out which courier will be assigned the order and the approximate transport time from pickup to delivery => DeliveryLatencyEstimateMade
event emittedOrderSentToRestaurant
and updates its order status (for presentation to the user) to in preparation
OrderSentToRestaurant
DeliveryLatencyEstimateMade
eventDeliveryEstimateLatencyEstimateMade
and updates its model (delivery time remains unknown
)OrderReadyForPickupAt
event emittedOrderReadyForPickup
, refines courier assignment decisionsOrderReadyForPickupAt
event, combines with the latest latency estimate to present a predicted delivery time to the userand so forth. Each service is autonomous and in control of its data representation and free to ignore or interpret the events as it sees fit. Note that this implies eventual consistency (the restaurant service will know about when the order is expected to be ready for pickup before the courier or client services know about that), though microservice autonomy already effectively ruled out strong consistency.