Transactions and writes
Write methods live in the Repository only; transaction boundaries sit in app/domain and assertions hold them.
Where writes go
- The only exit for writes (insert / update / delete) is the Repository; a Service never holds a Mapper.
- Cross-table consistency and multi-step flows go into
domain/handler; AppService only calls them.
Transaction boundaries
- Boundaries live in the
appanddomainlayers. @Transactionalin theRepositorylayer fails the build — fine-grained transactions make the call site impossible to compose.- No remote calls or slow work inside a transaction; do those after commit.
Batching and deletes
- Batch writes go through the single exit, avoiding "half succeeded, half failed".
- Deletes are logical by default; a physical delete needs an explicit reason and its own review.
Why one exit
Scattered writes lead directly to missed audit entries, inconsistent transaction boundaries and cache invalidation written three different ways. With one exit, all three happen in one place.
Last updated 2026-10-09Edit this page →