---
title: "Change one aggregate per transaction · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/domain-model/one-aggregate-per-transaction
id: ARC-76
level: Recommended
updated: 2026-10-22
tokens: 725
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Change one aggregate per transaction

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Domain model](https://agentwranglers.se/playbook/architecture/domain-model.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: ARC-76
- Level: Recommended
- Chapter: [Domain model](https://agentwranglers.se/playbook/architecture/domain-model.md)
- Rule: Save one aggregate per database transaction. Refer to other aggregates by their ID, and update them afterwards through events.
- Check: No aggregate type has a field whose type is another aggregate's root, which the type checker or an ArchUnit rule can test. Each repository's save method writes the tables of one aggregate only.
- How: A transaction that changes an order, a customer and the stock at once locks all three, and two such transactions deadlock or block each other. When one aggregate holds another as an object, code changes both without noticing. Hold a `CustomerId`, not a `Customer`. When placing an order must reduce stock, save the order with an event in an outbox, as [Send side effects through an outbox](https://agentwranglers.se/playbook/data/transactions-and-concurrency/outbox.md) says. The stock handler then changes the stock in its own transaction. Inside one aggregate, follow [Wrap multi-step changes in a transaction](https://agentwranglers.se/playbook/data/transactions-and-concurrency/transactions.md).

## Sources

- [.NET architecture guide: transactions across aggregates](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation#single-transaction-across-aggregates-versus-eventual-consistency-across-aggregates)

## Related rules

- DAT-18 [Send side effects through an outbox](https://agentwranglers.se/playbook/data/transactions-and-concurrency/outbox.md) in Data and databases
- DAT-14 [Wrap multi-step changes in a transaction](https://agentwranglers.se/playbook/data/transactions-and-concurrency/transactions.md) in Data and databases

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/domain-model/one-aggregate-per-transaction">Agent Wranglers clean code and architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Change an aggregate only through its root](https://agentwranglers.se/playbook/architecture/domain-model/aggregate-root.md)
- Next: [Translate outside models at the boundary](https://agentwranglers.se/playbook/architecture/domain-model/anti-corruption-layer.md)
- [Domain model](https://agentwranglers.se/playbook/architecture/domain-model.md)
