I am confused about at least one thing after reading Vaughn Vernon's Implementing Domain-Driven Design. In Chapter 12 Repositories he says that transactions are managed in the application layer. But he also says that an aggregate is synonymous with transactional consistency boundary. And since repositories provide global access to aggregates, why couldn't transactions be managed in repositories? Is it because the rule aggregate == transactional consistency boundary is only a rule of thumb that must sometimes be broken, or is there something else to it?
3 Answers
why couldn't transactions be managed in repositories?
Because a Repository isn't an abstraction for "a business transaction"
, a Repository is an abstraction for "a collection of domain objects that you can take from or add to"
.
By definition, a transaction has a beginning and an end. It is a process. A Repository isn't. The relationship between Transaction and Repository is not is-a, it's has-a. The transaction uses its repository.
When we say that Aggregate should be the consistency boundary, we mean that it should be the only block of state encompassed by a transaction, not that an Aggregate should be the same thing as a transaction.

- 13,738
- 1
- 32
- 51
New answer
It's good to be reminded of the strange things I've written years ago...
So, here is how I would answer this question today:
Indeed, aggregate boundaries are consistency boundaries. This definition implies not only that it is a boundary of a technical transaction, but also the fact the aggregate must ensure that the operation that has been executed on it doesn't bring the aggregate itself to an invalid state. Those invariants are rarely technical but most often business-oriented.
Speaking of persistence, that's exactly what is mentioned in the accepted answer. Repositories take care of persistence. There are tons of repository implementations that are physically unable to ensure transactions from start to end. In addition, some cases might involve application-specific concerns like being able to handle optimistic concurrency and so on. That's not something repositories can do. Repositories, physically, take care to retrieve the aggregate state from some persistence before the operation is executed and persist the state mutation back when the operation is completed.
Therefore, the transaction for command handling becomes an application concern, not persistence concern.
Old answer
Usually, repositories get instantiated with some Session or UnitOfWork injected to them in the constructor, to obtain the persistent storage connection. It is beneficial to share the same connection inside one application service call and usually such call itself is made transactional, including both reading and writing. This, I hope, explains the basic principle. Vernon gives examples of @Transactional
-annotated application service methods.
Also, on page 367 you can find a section called Reasons to Break the Rule, where he explains why you would justify updating multiple aggregates in one transaction.
The last point from me that you should remember that collection-style repositories do not know much about how stuff gets committed to the storage. They keep track of the changes and report back to the UoW, which does the commit (or rollback).

- 17,291
- 7
- 48
- 81

- 17,944
- 2
- 55
- 83
One of the reasons that transaction is on application layer is that the execution of ApplicationService
typically changes one Aggregate
and this Aggregate
publishes DomainEvents
that have to be store along Aggregates
in the same transaction.

- 5,011
- 2
- 25
- 30