Java Interview Questions

Spring Transaction Propagation: REQUIRED, REQUIRES_NEW, and the Common Pitfalls

"Explain Spring transaction propagation modes and common @Transactional pitfalls."

Why Interviewers Ask This

Transactional behavior is a leading cause of production data-consistency bugs. Interviewers use this to separate candidates who know the declarative API from those who understand what the proxy, rollback rules, and self-invocation actually do.

How to Answer

  1. 1

    Seven propagation modes; the three that matter: REQUIRED (default) joins an existing transaction or creates one; REQUIRES_NEW suspends the outer and starts a fresh inner transaction; NESTED creates a savepoint within the outer transaction.

  2. 2

    Rollback rule: by default Spring only rolls back on RuntimeException and Error, NOT checked exceptions. Configure rollbackFor = Exception.class if you throw checked exceptions.

  3. 3

    Self-invocation pitfall: this.methodB() bypasses the proxy, so the inner @Transactional never activates.

  4. 4

    Private method pitfall: Spring AOP can't proxy private methods, so @Transactional on a private method is silently ignored.

  5. 5

    Exception-caught pitfall: if you catch the exception inside the @Transactional method without rethrowing, no exception propagates and Spring commits the transaction despite the error.

Sample Answer

Spring @Transactional has seven propagation modes but three that really matter. REQUIRED is the default — if a transaction exists, join it; if not, start a new one. So calling a REQUIRED method from another REQUIRED method reuses the same transaction, and a rollback in the inner method rolls back the whole thing. REQUIRES_NEW suspends any existing transaction and starts a brand new one; the inner rollback only affects the inner work, and the outer can commit independently. Use this for things like audit logs that must persist even if the business operation fails. NESTED uses a savepoint inside the outer transaction — inner rollback rolls back to the savepoint without killing the outer. Four common pitfalls. First, the default rollback rule only fires on RuntimeException and Error. If you throw a checked IOException, Spring commits the transaction. Fix: @Transactional(rollbackFor = Exception.class). Second, self-invocation — this.methodB() from within methodA() of the same class bypasses the Spring proxy, so @Transactional on methodB is never triggered. Fix: inject the bean into itself, use AopContext.currentProxy(), or restructure. Third, private methods — Spring AOP is subclass-based (CGLIB) or interface-based (JDK), neither can intercept private methods, so @Transactional on private is silently ignored. Fourth, catching the exception inside the method. If your code try/catches the DB exception and doesn't rethrow, Spring sees no exception and commits. The fix is either rethrow or explicitly call TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(). In production I treat @Transactional as "marks a method as needing a transaction — now verify the proxy path, the exception will propagate, and no self-calls."

Pro Tips

  • Always mention the four pitfalls — they're the practical differentiator.

  • "Checked exceptions don't roll back by default" is the single most common bug I've seen in code review.

  • Be ready to discuss REQUIRES_NEW for audit-log and notification patterns.

  • If you blank on rollbackFor syntax during the interview, HireMe AI can surface the exact annotation.

Frequently Asked Questions

When should I use REQUIRES_NEW?

When the inner work must succeed or fail independently of the outer — typical examples are audit logs, outbox writes, or sending notifications.

What's the difference between NESTED and REQUIRES_NEW?

NESTED shares the outer connection and uses a savepoint — inner rollback doesn't kill outer but outer rollback rolls back inner. REQUIRES_NEW uses a separate physical transaction — truly independent.

Does @Transactional work across threads?

No — Spring transactions are thread-bound via ThreadLocal. Passing work to a new thread (executor, @Async) loses the transaction context.

Worried About Going Blank in Your Interview?

HireMe AI listens to your interview in real-time, detects questions, and generates instant answer suggestions — so you never freeze up again.

Try HireMe AI Free