Spring's @Transactional propagation defaults can silently cause data inconsistency. A common case: an inner method marked REQUIRED (the default) joins the outer transaction, so when the inner fails and rolls back, it takes the outer transaction's work with it — even if the outer intended to catch and continue.
The bug: audit logging or notification side-effects get rolled back along with the main transaction, or conversely, REQUIRES_NEW isolates failures but opens a second connection, risking pool exhaustion under load.
Reproduce both failure modes. Compare propagation behaviors: REQUIRED (default, baseline bug), REQUIRES_NEW (isolation with connection cost), NESTED (savepoint-based partial rollback). Measure connection usage and correctness across strategies.
Correctness invariant: inner-transaction failure must not corrupt outer-transaction state. Benchmarks should show the connection overhead of REQUIRES_NEW under concurrent load. Standard module layout, AC-1 through AC-5.
Spring's
@Transactionalpropagation defaults can silently cause data inconsistency. A common case: an inner method markedREQUIRED(the default) joins the outer transaction, so when the inner fails and rolls back, it takes the outer transaction's work with it — even if the outer intended to catch and continue.The bug: audit logging or notification side-effects get rolled back along with the main transaction, or conversely,
REQUIRES_NEWisolates failures but opens a second connection, risking pool exhaustion under load.Reproduce both failure modes. Compare propagation behaviors:
REQUIRED(default, baseline bug),REQUIRES_NEW(isolation with connection cost),NESTED(savepoint-based partial rollback). Measure connection usage and correctness across strategies.Correctness invariant: inner-transaction failure must not corrupt outer-transaction state. Benchmarks should show the connection overhead of
REQUIRES_NEWunder concurrent load. Standard module layout, AC-1 through AC-5.