org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was ...
ID: java/spring-transaction-timeout
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 21 | active | — | — | — |
Root Cause
A Spring-managed transaction exceeded its configured timeout. The default Spring transaction timeout is often inherited from the underlying transaction manager or database connection pool. When a @Transactional method takes longer than the timeout, Spring marks the transaction for rollback. The actual timeout enforcement depends on the transaction manager and may only be checked at certain points (e.g., before executing the next JDBC statement).
genericWorkarounds
-
90% success Set an appropriate per-method transaction timeout and optimize the slow operation
Use @Transactional(timeout = 30) on the specific method (timeout in seconds). Profile the method to find the slow operation: is it a slow query, external API call, or N+1 select problem? Optimize the database query (add indexes, reduce data fetched). Move non-transactional work (HTTP calls, file I/O) outside the @Transactional boundary.
-
85% success Split long-running operations into smaller transactional units
Break the operation into multiple smaller transactions using TransactionTemplate or @Transactional(propagation = REQUIRES_NEW) on helper methods (must be in a different Spring bean due to proxy-based AOP). Process records in batches, committing after each batch. Use Spring Batch for very large dataset operations.
Dead Ends
Common approaches that don't work:
-
Setting the timeout to an extremely large value (e.g., Integer.MAX_VALUE) to prevent timeouts
70% fail
Very large timeouts mask performance problems and can hold database locks for extended periods, causing cascading failures for other transactions. A long-running transaction also consumes database connection pool resources, potentially exhausting the pool for other requests.
-
Adding @Transactional(timeout=X) at the class level to fix a timeout in one specific method
60% fail
Class-level @Transactional applies to all public methods. Setting a long timeout at the class level to fix one slow method gives every method an unnecessarily long timeout, masking performance issues in the fast methods. Each method should have an appropriate timeout.