Propagation answers one question: when a @Transactional method is called, should it join the caller's transaction, start its own, or run without one? REQUIRED is the default and covers ~95% of cases; the others exist for specific needs, and interviewers want to know you can reach for the right one.
The seven values
REQUIRED join the current tx, or start one if none (DEFAULT)
REQUIRES_NEW always start a NEW tx; suspend the caller's until this commits/rolls back
NESTED run in a savepoint inside the current tx (partial rollback)
SUPPORTS join a tx if one exists; otherwise run non-transactionally
NOT_SUPPORTED suspend any current tx; run non-transactionally
MANDATORY must run in an existing tx; throw if there is none
NEVER must NOT run in a tx; throw if one exists
The three that matter most
REQUIRED — the default. Inner and outer share one physical transaction; one rollback rolls back everything. If inner() throws and is caught by outer(), the whole thing is still doomed — the transaction is marked rollback-only.
REQUIRES_NEW — suspends the caller and runs in an independent transaction with its own commit/rollback. The classic use is audit logging: you want the log row to commit even if the business transaction rolls back.
@Transactional // outer
public void process(Order o) {
audit.record("started", o); // REQUIRES_NEW → commits independently
risky(o); // if this throws, outer rolls back,
} // but the audit row survives
@Transactional(propagation = REQUIRES_NEW)
public void record(...) { ... }
NESTED — uses a JDBC savepoint inside the outer transaction. Rolling back the inner part returns to the savepoint without killing the whole transaction; but if the outer rolls back, the nested work goes too (unlike REQUIRES_NEW, which already committed). Requires a savepoint-capable JDBC driver.
The self-invocation gotcha
Spring's @Transactional is proxy-based AOP. Calling this.inner() from outer() in the same bean bypasses the proxy entirely — propagation (and even the annotation) is ignored. The advice only fires on calls that go through the proxy, i.e. from another bean. This catches everyone at least once.