Transaction boundaries
A transaction boundary summarizes changes that succeed or fail together. Outside of this border, cooperation needs its own error handling.
- NuclearityAll or nothing.
- Commit and RollbackWrite or reject it.
- BoundaryOnly common, no external calls.
Context
Why this is important
If the system falls in the middle of storage, half a state remains. A transaction makes it all or nothing. Their boundary includes only what must apply in common, typically an aggregate. External calls are outside. Across several transactions, you need a saga.
This building block explains local nuclear changes. For flows across multiple transactions, see Saga.
At a glance · All or nothing within a boundary
Where does it break off?
The checkout stores order B-1042 with position P-7 and order amount in the shop database. The charge to the payment provider is an external call.
This is how you read the picture
- Nuclearity With a transaction after the crash, either everything or nothing is in the database.
- Commit and Rollback Before commit rolls back; only after commit does all three fields remain filled.
- Boundary The payment provider remains charged, even if the database rolls back.
- Order to be established
- Position P-7 Writing
- Setting the order amount
- Commit
In the database after the crash · by step 1
- Order B-1042
- —
- Position P-7
- —
- Order amount
- —
Benefits & limitations
Helps if:
- A common invariant is preserved by an atomic transaction over all associated local changes.
- Isolation and conflict handling give concurrent writes a safe outcome.
- A local transaction durably stores a database change and the intent to send together.
Boundaries
- External calls lie outside the local transaction; their outcomes need their own durable status. See Transactional Outbox.
- Long transactions hold locks and slow other work; measure duration and lock waiting time.
- Transactions across other modules' data areas couple those modules; consider a Saga or Outbox instead.
In practice
- Name the invariant to protect and limit the local transaction to the changes needed for it. This grounds the boundary in business rules.
- Test concurrent access with the chosen isolation or versioning rules. Measure lock duration and conflicts so atomicity does not silently constrain throughput.
- Handle publication and external effects outside a local transaction explicitly. Transactional Outbox links the intent to send to the local change; Saga coordinates distributed steps.
Read the detailed explanation
A local transaction makes related changes atomically visible: all included writes commit together or roll back together. Isolation additionally describes how concurrent transactions observe one another.
The boundary should contain exactly the business invariants that must hold together. It covers only resources governed by a shared transaction mechanism. External effects need separate coordination; distributed processes make progress and intermediate states part of the model.
Transactional Outbox uses local atomicity to record a durable intent to send; Saga coordinates several local transactions with follow-up actions defined by business rules.
ACID stands for Atomicity, Consistency, Isolation and Durability: the guarantees of a local transaction. Two-Phase Commit (2PC) extends atomic commitment across participants but can block them, which is why distributed processes often use a Saga.
A transaction alone does not prevent every concurrency problem: when two users change the same order simultaneously, the second change may overwrite the first (Lost Update). Appropriate isolation levels or a version check on write (optimistic locking) address this.
Check your understanding
Test yourself in three stages
ReadingCheck in the picture
You choose Autocommit and leave the system by step 1 crashing. What then is in the database?
View the solution with justification
Only the order B-1042. Position P-7 and order amount missing, the invariant “at least one position” is injured.
ApplyingTransferred to a new situation
A transaction that the payment provider is charged before commit, crash by step 3. What is in the database, what is in the provider?
View the solution with justification
The database rolls back and contains nothing. The provider shall: 49,90 € but already burdened, because the external call is outside the transaction.
EvaluateWeighing an alternative
The team wants to pack ordering and warehouse reservation into a joint transaction because both are in the same database. How do you rate that?
View the solution with justification
Advantage: Both succeed or fail together, without an intermediate state. Disadvantage: The transaction links two data areas with their own data sovereignty and extends blocks. Recommendation: Merge only if a common invariant requires it; otherwise separate transactions with Saga or Outbox.
Explore further
These building blocks continue the thoughts of this page.