Search code examples
design-patternsdomain-driven-designmodeling

Difference between messaging and transaction in DDD?


So in DDD there are transactions (presumably business transaction) which should happen on a single aggregation root, and messaging or events which happens between domains / aggregates as uni-directional notifications.

I'm having a hard time understanding semantics of such separation. I can't formulate it in a one shot, so here are several questions of approximately same class, which should converge in a single answer (I hope).

  1. Does transactions is about synchronous communication and events is about asynchronous in DDD?
    1. So, is it an attempt to show basically strong and eventual consistent communication paths?
  2. Or what then the difference between spinning single transaction across several aggregates and sending a sequential events between them (when one sending own event after processing event from the previous aggregation root), like in actors model?
    1. Shall we consider the last one also a single transaction then, as basically we guaranteeing (just on the model level) that events are fired and processed?
    2. In this case transaction is about parallel and messaging is about sequential processing?
  3. Shall I consider both transaction and events as an implementation of single business transaction on the model level?

This current communication dichotomy with relation to aggregation roots consistency issues seems either redundant or overlapping with each other, and I don't see they way how it is overlapping. In general form we speak about data propagation and in DDD it's became confusing.

This data propagation topic in DDD looks like an ugly version described in actors model.


Solution

  • The basic building bloc of DDD is a bounded context. Bounded contexts regroup highly coupled domain objects that can be updated together atomically, in a single transaction. Transactions handle intra-context updates.

    Loosely coupled objects that are updated separately are spread across different bounded contexts. Although different bounded context can be collocated in the same service, with the same database backend, they are designed as independent pieces of software that can easily spread in different services with different databases backends, adopting a microservice pattern. This allows better scalability, better separation of concerns, and lowers the risk of regressions when updating a context.

    Sometimes, you need to update objects from different bounded contexts, or you need different bounded context to ensure business integrity of the operation. This causes a major problem known as distributed transactions, as what you are trying to achieve is a single atomic transaction over a distributed series of bounded context, hosted in different services, backed by different database technologies. You can use 2-phase commit or saga pattern techniques to solve this problem. These techniques imply inter-context communication that usually occur through usage of event and messaging.