When Do You Need a Database Transaction?
Fast recall
Quick revision
Core answer
Practical judgment — knowing when to use transactions versus when a single operation doesn't need explicit transaction management.
Choosing a boundary from the number of repository calls alone instead of the atomicity, snapshot, locking, and resource requirements.
Name specific real-world scenarios: order creation with inventory updates, money transfers, user registration with email verification records — and explain why each requires a transaction.
Interview-ready guide
Interview answer
Use a database transaction when several operations on the same transactional resource must commit or roll back together.
Saving an order, its line items, and a stock change in one database is a clear example. Transactions also matter for reads that need a consistent snapshot, a lock, or a defined isolation level. One independent SQL statement is already transactional, so application code may not need a wider boundary.
Concurrency still needs a specific control: isolation, a row lock, optimistic versioning, or a conditional update. A remote payment API cannot normally join the local database transaction, so use idempotency and a recovery pattern such as an outbox or saga. Keep the boundary around the database work and avoid holding it open during slow network calls.
When Do You Need a Database Transaction
Direct Answer
Use an explicit transaction when several database operations must commit or roll back as one unit, or when reads need a defined isolation level, lock, or consistent snapshot. One SQL statement is transactional too, but application code may not need to open a wider boundary for an independent statement.
Code Example
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
int changed = inventoryRepo.reserveIfAvailable(
order.getItemId(), order.getQty());
if (changed != 1) {
throw new OutOfStockException(order.getItemId());
}
orderRepo.save(order);
}
}
The transaction keeps the successful stock reservation and order insert in one unit. The conditional update prevents stock from dropping below the encoded limit; the transaction boundary alone would not prevent that race.
Common Mistakes & Pitfalls
- Making the boundary too wide: Holding a database transaction open across slow network calls increases lock time and connection use.
- Making the boundary too narrow: Separate repository calls can commit independently when the business operation needs one unit.
- Assuming
readOnly = trueis mandatory: It is an intent hint whose effect depends on the transaction manager and provider. Use it deliberately, not as a universal performance rule.
Check your understanding
Answer these without looking back at the article.
- Should @Transactional be on the service layer or the repository layer?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.