Choosing a transaction propagation level for calls that span multiple services depends on whether those calls must be atomic together or need to stay isolated from each other, and each choice carries its own risk.
Key Points: • REQUIRED (the default) joins the caller's existing transaction if one exists, keeping tightly coupled operations atomic together. • REQUIRES_NEW always starts a fresh, independent transaction, useful when a call (like audit logging) must commit regardless of whether the outer transaction later rolls back. • A pitfall of REQUIRED across many nested calls is longer-held locks and higher chances of contention or deadlocks under concurrent load. • A pitfall of REQUIRES_NEW is added resource usage from managing multiple simultaneous transactions, and more complex rollback logic if an inner transaction succeeds but the outer one later fails. • For calls that genuinely cross service/database boundaries, no single database transaction can span them at all -- that calls for a saga pattern with compensating actions instead.
Example: An order-placement flow uses REQUIRED so inventory deduction and order creation commit or roll back together, but logs the audit trail with REQUIRES_NEW so the audit record is preserved even if the order itself later fails and rolls back.
Interview Tip: A concise interview answer is:
"I'd default to REQUIRED for operations that must succeed or fail together, and reach for REQUIRES_NEW only when something, like audit logging, needs to survive an outer rollback. The tradeoff is that REQUIRED risks longer lock contention under load, while REQUIRES_NEW adds resource overhead and more complex failure handling -- and for calls that cross separate databases entirely, neither works, so I'd use a saga pattern instead."