We are developing an application where providers can offer their products and consumers can buy them (sort of marketplace). We try to apply DDD concepts into our model design and the implementation follows a microservices style. This implies that the data belongs to a Bounded Context (BC) and only the microservices within that BC can access it. Outside that BC, specific information can only be either queried through a public interface of the BC or by subscribing to events published by that BC.
My question is about the design of the Orders. Orders are placed by consumers and accepted and fulfilled by providers. They can also be manipulated by customer service. An order right now contains only products from a single provider, but I might be asked in the future to support buying from multiple providers at once.
All implementations I've seen of similar systems contain a single Order model, which tends to be really bloated with information about the products, the provider, the consumer, invoicing, deliveries, payments, etc. I am trying to avoid that, but I am facing the question of "Who owns the order"?
I can think of the following answers:
- There is an Orders bounded context which is accessed by both the consumer and the provider. This means that the consumer API has a Place Order operation that talks to the Orders BC and creates an order and the Providers API has an operation like Accept Order which talks to the same Orders BC and changes the status of that same order model.
- There are 2 Orders BCs: Consumer Orders and Provider Orders. The Consumer API places an order in the Consumer BC. This creates the order and publishes a ConsumerOrderCreatedEvent. The ProviderOrders BC listens to that event an creates a local Order (ProviderOrder) which references the ConsumerOrder. Through the Provider API, the order can be accepted, which will publish a ProviderOrderAcceptedEvent, which will allow the ConsumerOrders to mark the order as accepted and notify the consumer about it.
My personal preferred approach is option 2 as I can see several benefits (see below), but I'm not sure if they are worth the added complexity.
I can't formulate a specific question, but as this problem must have been solved thousands of times, I'd like to know if there is one preferred approach, well-known solution or reference design that can help me.
Benefits of separate ProviderOrders and ConsumerOrders bounded contexts:
- A single ConsumerOrder can generate multiple ProviderOrders (if the order contains products from multiple providers
- The workflow of a ProviderOrder might be different/more complex than the workflow of a ConsumerOrder.
- Both the consumer and the provider need to see their order history, which I envision as a denormalized table for fast reads, but both order histories contain different data (ie consumer orders contain provider information and provider orders contain consumer information) and are queried differently (by the consumer and by provider). This can be implemented in single table obviously, but it seems cleaner if they are 2 tables dedicated to a single purpose.
- Data isolation/partitioning. Consumer orders are always accessed by consumer Id, Provider Orders are always accessed by ProviderId.
I'm having a very interesting conversation about this topic on a separate forum, so I thought I should link it here, in case someone wants to read more thoughts on this topic. Same question on NServiceBus discussion board
Note: This is implemented in .NET, by multiple teams, from multiple repositories and Visual Studio Solutions, hosted in a Service Fabric cluster and using NServiceBus for messaging.