# ADR-JPA-002 — Retry re-runs the whole use case - Status: Accepted - Date: 2026-08-11 - Design: §19.2 ## Context Optimistic conflicts, deadlocks, and serialization failures are recoverable. The question is what unit gets retried: the failed statement, the transaction, or the use case. ## Decision The whole use case, in a new transaction with a new Persistence Context. `FullTransactionRetryCoordinator` re-enters `JpaTransactionExecutor` for every attempt, and the retry advice is ordered outside Spring's transaction advice so each attempt begins a new transaction. ## Consequences Statement-level retry is wrong for exactly the failures being retried. An optimistic conflict means the state the attempt computed against is no longer the committed state; re-issuing the same statement computes the same wrong answer against a version that has moved on. The domain rules have to run again over reloaded data, which means the whole use case. Reusing the Persistence Context would be equally wrong: the second attempt would read the first attempt's stale entities out of the first-level cache. And with the advice ordering inverted, the retry loop would run inside one transaction that has already been marked rollback-only, so the second attempt fails immediately without executing anything. The cost is that a retryable use case must be safe to run from scratch — no irreversible external effect before the commit. `IrreversibleSideEffectContext` lets a use case declare when that does not hold, and the policy then refuses to retry it whatever budget remains. ## Enforcement `FullTransactionRetryCoordinatorTest`; `RetryableJpaTransactionInterceptor.DEFAULT_ORDER`.