Transaction Mastery Interview Questions
ACID, isolation levels, locking & MVCC, Spring @Transactional internals, distributed transactions (2PC, Saga, Outbox/CDC), and Kafka transactions — from the bank-counter story to production incident response.
← Learn this topic from scratch firstWhat Is a Transaction?
Is a single INSERT statement a transaction?
beginnerYes — most databases wrap every individual statement in an implicit transaction if you haven't started one explicitly (this is called "autocommit mode," covered in Chapter 06). A transaction can contain exactly one operation or hundreds; the concept doesn't require multiple statements.
In your own words, what is a database transaction?
beginnerA group of operations treated as one unit — either all of them succeed, or none of them do.
Give a real-world (non-technical) example of a transaction.
beginnerA bank transfer: debit one account, credit another — both must happen, or neither should.
Why isn't "just do the operations one after another in application code" sufficient?
intermediateWithout a transaction boundary, a crash or concurrent access between steps can leave the system in a partially-updated, inconsistent state that no single step's own error handling can detect or fix.
Can a transaction consist of read-only operations?
advancedYes — a multi-step read that needs a consistent view across several queries (e.g. a financial report reading several tables) also needs a transaction, specifically for isolation guarantees (Chapter 04), even though nothing is being written.
When does the "single transaction" mental model stop being applicable at all?
expertOnce a logical business operation spans more than one independently-deployed database or service — at that point you need Saga, Outbox, or 2PC (Chapters 16–18), not a bigger local transaction.
What are the only two possible endings of a transaction?
beginnerCOMMIT (all changes take effect) or ROLLBACK (all changes are discarded) — never a partial outcome.
What's the shared shape across the ATM, flight, and shopping examples?
beginnerMultiple steps that must either all succeed together, or leave the system completely unchanged if any one fails.
Atomicity
What does atomicity guarantee?
beginnerThat a transaction's operations either all take effect, or none do — no partial state is ever observable.
How does a database implement atomicity internally?
intermediateTypically via an undo log — the previous value of each changed row is recorded before modification, so a rollback or crash recovery can restore it.
If a transaction sends an email via a third-party API and then rolls back, is the email un-sent?
advancedNo — atomicity only covers operations within the transactional resource (the database); external side effects like an email API call are not covered and will not be undone.
How would you safely combine "update the database" and "call an external API" as one logical, all-or-nothing unit?
expertDon't call the external API inside the transaction at all — persist an event/outbox record in the same transaction (Chapter 18's Outbox Pattern) and have a separate process call the external API afterward, based on that durably-committed record.
Consistency
What's the difference between ACID consistency and CAP consistency?
beginnerACID consistency means data satisfies your defined constraints; CAP consistency means every read across distributed nodes sees the latest write — different concepts that happen to share a name.
Does ACID consistency have its own dedicated internal mechanism, like atomicity has undo logs?
intermediateNo — it emerges from atomicity plus isolation plus the constraints (foreign keys, checks) you actually define.
Can a database with perfect atomicity and isolation still be "inconsistent"?
advancedYes — if you never define the constraints that encode your actual business rules, the database has nothing to enforce, and logically invalid data can still be committed.
Isolation & Anomalies
What does isolation control?
beginnerHow much of another concurrently running transaction's work is visible to you before it commits.
Order the four isolation levels from weakest to strongest.
intermediateRead Uncommitted → Read Committed → Repeatable Read → Serializable.
Why does PostgreSQL's Repeatable Read prevent phantom reads, when the SQL standard doesn't require it to?
advancedPostgreSQL implements Repeatable Read using a single consistent MVCC snapshot taken at the start of the transaction — new rows committed by other transactions simply aren't visible in that snapshot, which incidentally also blocks phantoms, stronger than the standard's minimum requirement.
How would you decide isolation level on a per-operation, not per-application, basis?
expertDefault the application to Read Committed, and explicitly elevate to Repeatable Read/Serializable only for specific operations (financial reports, multi-step invariant checks) where the extra correctness is worth the concurrency cost — isolation level is a per-transaction decision, not a single glob
What's the difference between a dirty read and a non-repeatable read?
beginnerA dirty read sees uncommitted data; a non-repeatable read sees committed data that changed between two reads of the same row within one transaction.
Which isolation level is the default in PostgreSQL?
beginnerRead Committed.
Which isolation level is the default in MySQL/InnoDB?
beginnerRepeatable Read.
Which anomaly does Serializable prevent that Repeatable Read (per the SQL standard) does not?
beginnerPhantom reads.
Durability
What does durability guarantee?
beginnerThat once a transaction is committed, its effects survive any later crash, including a full power loss.
Why does the database write to a separate log before updating the real data files?
intermediateSequential log appends are much faster than in-place updates to indexed data files, and the log lets a crash mid-update be safely recovered by replaying it, rather than risking a corrupted data file.
What's the practical risk of setting synchronous_commit = off on a payments database?
advancedA narrow window exists where a transaction the client was told "committed" could actually be lost on a crash before its WAL entry was truly durable — unacceptable for money-moving operations.
SQL Transaction Control
What does autocommit mode mean?
beginnerEvery individual SQL statement is automatically committed as its own implicit transaction, unless you explicitly BEGIN one yourself.
What's the difference between ROLLBACK and ROLLBACK TO SAVEPOINT?
intermediateROLLBACK discards the entire transaction; ROLLBACK TO SAVEPOINT discards only the work done after that named savepoint, leaving earlier work in the same transaction intact and still pending commit.
Does standard SQL support true nested transactions?
advancedNo — SAVEPOINT provides partial-rollback behavior within a single transaction, but there is no independently committable inner transaction in standard SQL.
Locking, MVCC & Deadlocks
What's the core difference between optimistic and pessimistic locking?
beginnerPessimistic locking blocks other transactions immediately on read; optimistic locking allows concurrent reads and only detects a conflict at write time via a version check.
Why doesn't a long-running SELECT block a concurrent UPDATE under PostgreSQL's MVCC?
intermediateThey operate on different row versions — the reader sees a consistent snapshot from when it started, while the writer creates a new version, with no shared lock to contend over.
What's the actual root cause of most production deadlocks, and what's the real fix (not just a mitigation)?
advancedInconsistent lock acquisition order across different code paths; the real fix is enforcing a consistent lock order everywhere (e.g. always by ascending primary key), not just adding retry logic.
When would you choose pessimistic locking over optimistic, at scale?
expertWhen contention on a specific resource is genuinely high and expected (flash sales, limited-inventory drops) — optimistic locking under heavy contention just produces a storm of failed, retried transactions instead of preventing the contention in the first place.
@Transactional Fundamentals
Does @Transactional roll back on every exception by default?
beginnerNo — only on unchecked exceptions (RuntimeException) and Errors by default; checked exceptions commit unless rollbackFor is specified.
Does readOnly = true prevent a write statement from executing?
intermediateNo — it's a hint for optimization (skipping dirty-checking, potentially routing to a replica), not an enforced restriction.
Why is this default rollback behavior considered a design trap in real codebases?
advancedBecause a developer using checked exceptions for validation errors (a very natural Java instinct) can silently commit partial, invalid state without any error at the database level — the bug only surfaces as corrupted data downstream.
Propagation & Isolation in Spring
What's the default propagation type in Spring?
beginnerREQUIRED — join the existing transaction if one is present, or start a new one if not.
What's the real difference between REQUIRES_NEW and NESTED?
intermediateREQUIRES_NEW is a genuinely separate database transaction on a separate connection that commits independently; NESTED is a SAVEPOINT within the same single transaction, with no independent commit.
Why doesn't setting isolation = SERIALIZABLE on a REQUIRED method that joins an existing transaction do anything?
advancedIsolation level is fixed when the physical transaction actually begins; a method joining an already-open transaction via REQUIRED doesn't start a new physical transaction, so its isolation annotation is ignored.
When would REQUIRES_NEW create a deadlock risk against its own caller?
expertIf the inner (REQUIRES_NEW) transaction tries to lock a row the outer, currently-suspended transaction already holds a lock on — since they're separate physical transactions on separate connections, the inner one can genuinely block waiting on the outer, which can't proceed until the inner one (whic
Transaction Manager Internals
How does Spring actually implement @Transactional under the hood?
beginnerVia an AOP proxy wrapping the bean — the proxy runs transaction begin/commit/rollback logic around a delegated call to the real method.
Why does calling this.someTransactionalMethod() from within the same class not create a transaction?
intermediatethis refers to the raw object, not the Spring-managed proxy — the call bypasses the proxy's TransactionInterceptor entirely.
What are the three ways to fix the self-invocation problem, and which is generally preferred?
advancedSplit into separate beans (preferred — cleanest), self-injection, or AopContext.currentProxy() with exposeProxy enabled — splitting into separate beans is preferred because it doesn't rely on exposing proxy internals.
Why would you use afterCommit() instead of just putting an email send at the end of a @Transactional method?
expertCode at the "end" of the method still runs before the proxy's actual commit — if the commit itself then fails, an email may have already been sent for a transaction that didn't actually persist; afterCommit() guarantees the callback only fires once the commit has genuinely succeeded.
Programmatic, Reactive & Nested Transactions
When would you use TransactionTemplate instead of @Transactional?
beginnerWhen you need transaction boundaries at a finer granularity than a whole method, or decided conditionally at runtime — e.g. per-chunk commits in a batch loop.
Why does classic @Transactional not work correctly in a reactive application?
intermediateIt relies on thread-local storage to track the current transaction, but reactive execution can hop across threads, breaking that association.
What's the real danger of calling a blocking JDBC repository from a reactive WebFlux service?
advancedIt blocks the shared event-loop thread, potentially stalling many other concurrent requests being multiplexed on that same thread — not just the one call.
Persistence Context & Dirty Checking
Why does modifying a loaded entity's field update the database without an explicit save() call?
beginnerHibernate's dirty checking compares the entity's current state against a stored snapshot at flush time and auto-generates the necessary UPDATE.
What's the difference between flush and commit?
intermediateFlush synchronizes pending changes to the database via SQL; commit makes already-flushed changes permanent — flush can happen multiple times before a single commit.
Why does modifying a detached entity silently do nothing?
advancedThere's no persistence context left tracking it for dirty checking — the change exists only in the Java object's memory, with nothing left to compare it against or flush it via.
Why might you deliberately set FlushMode.COMMIT instead of the default AUTO?
expertTo avoid the (sometimes surprising) performance cost of automatic pre-query flushes when you know your queries don't need to see not-yet-flushed pending changes — trading a small correctness convenience for predictable, batched flush timing.
Entity Lifecycle, Caching & Transaction Boundaries
What are the four entity states in JPA?
beginnerTransient, Managed, Detached, Removed.
Is the second-level cache enabled by default?
intermediateNo — it must be explicitly configured and opted into per entity, unlike the always-on first-level cache (persistence context).
Why does accessing a lazy relationship after the transaction ends throw an exception instead of returning stale data?
advancedThe lazy proxy needs an open persistence context to run its fetch query when first accessed — once the transaction (and persistence context) has closed, there's no session left to fetch through, so Hibernate throws rather than silently failing.
Why is "Open Session in View" generally considered an anti-pattern despite solving the LazyInitializationException problem?
expertIt hides real N+1 query problems by making lazy loading "just work" anywhere in the request, and blurs the transaction boundary across the entire web layer, making it harder to reason about exactly when and where database work happens.
MongoDB Transactions
Has MongoDB always supported atomicity, even before "transactions" existed as a named feature?
beginnerYes — every single-document write has always been fully atomic, regardless of how many fields or nested arrays it touches.
Why can't a standalone (non-replica-set) MongoDB instance run a multi-document transaction?
intermediateMulti-document transactions rely on the oplog and replication infrastructure that only exists in a replica set configuration.
What's MongoDB's own recommended default strategy regarding multi-document transactions?
advancedModel data so related, together-changing information lives in one document to get atomicity for free; use multi-document transactions only for genuinely cross-document operations that can't reasonably be modeled otherwise.
How does Spring's transaction abstraction let you swap SQL for MongoDB with minimal code change?
expertSpring's @Transactional and PlatformTransactionManager interface are resource-agnostic — swapping DataSourceTransactionManager/JpaTransactionManager for MongoTransactionManager changes the backing implementation without changing how your service code declares its transaction boundaries.
Why Local Transactions Fail
Why can't @Transactional protect a call to a different microservice's REST API?
beginner@Transactional only controls the local database connection/transaction it's bound to — a network call to another service is entirely outside that scope and cannot be rolled back by it.
What is the "dual-write problem," specifically?
intermediateThe inability to atomically commit a database write and a message publish (e.g. to Kafka) together — one can succeed while the other fails, since they're two separate systems.
Is this fundamentally a Spring/framework limitation, or a deeper constraint?
advancedA deeper constraint — a single database transaction is inherently scoped to one connection/database at the protocol level; no framework abstraction can make one COMMIT atomically span multiple independent databases.
Two-Phase Commit (2PC)
What are the two phases in Two-Phase Commit?
beginnerPrepare (vote) and Commit/Abort (decide) — nothing is actually committed until every participant has voted yes.
What happens to a participant that voted YES if the coordinator crashes before phase 2?
intermediateIt's stuck holding its locks indefinitely, unable to independently decide to commit or abort — this "blocking" behavior is 2PC's core structural weakness.
Why is 2PC generally avoided in modern microservices architectures?
advancedIt requires all participants to be synchronously available throughout both phases and introduces a coordinator as a new single point of failure — both work against microservices' goals of independent availability and scaling.
In a system design interview, when would choosing 2PC over Saga actually be the right call?
expertWhen strict, immediate consistency is a hard regulatory or correctness requirement, participant count is small and tightly controlled, and the availability/scaling cost is acceptable — genuinely rare in typical high-scale web/mobile backend systems, but real in some financial core-banking contexts.
Saga Pattern
What replaces atomicity in a Saga, since there's no real cross-service ROLLBACK?
beginnerCompensating transactions — forward-moving actions that reverse the effect of an already-committed earlier step.
What's the core structural difference between choreography and orchestration?
intermediateChoreography has no central coordinator — services react to each other's events independently; orchestration has an explicit orchestrator directing every step and deciding what happens next.
Why must every saga step be idempotent?
advancedEvent-driven communication (typically Kafka) commonly guarantees at-least-once delivery, so any step can be invoked more than once for the same logical event — non-idempotent steps would double-apply their effect (e.g. double-charging a card).
How would you design the ordering of steps in a saga with one genuinely irreversible action (like sending a physical package)?
expertPlace the irreversible action as the very last step in the saga, after every reversible step has already succeeded — this minimizes the window in which a failure would leave something un-compensable.
Outbox, Inbox & CDC
What problem does the Outbox Pattern solve?
beginnerThe dual-write problem — atomically recording a business change and its corresponding event, since the database and message broker can't be committed together directly.
Why is CDC (via Debezium) preferred over a hand-written polling relay?
intermediateCDC reads the database's own commit log directly, so it only ever sees truly committed changes and can resume precisely after a crash — a polling relay's separate "publish" and "mark published" steps have their own smaller dual-write gap.
How does the Inbox Pattern mirror the Outbox Pattern's core insight?
advancedBoth avoid trying to make two different systems atomic with each other — instead, they make an idempotency record and the actual effect atomic within a single local database transaction.
Why must the outbox table live in the exact same database as the business tables it's paired with?
expertThe entire mechanism depends on Chapter 02's local atomicity guarantee — the business write and outbox write must be part of the same physical database transaction, which is only possible if they share the same database.
Kafka Transactions & Exactly-Once Semantics
What does Kafka guarantee by default: at-most-once, at-least-once, or exactly-once?
beginnerAt-least-once — messages are never silently lost, but can be redelivered and processed more than once.
What two separate mechanisms combine to give Kafka exactly-once semantics?
intermediateThe idempotent producer (deduplicates retried sends via sequence numbers) and Kafka transactions (atomically group multiple writes, including offset commits, together).
Does read_committed alone give you exactly-once semantics?
advancedNo — it only ensures consumers don't see uncommitted/aborted transaction data (Kafka's version of preventing a dirty read); it must be paired with a transactional producer to get the full atomic guarantee.
Does Kafka's exactly-once semantics extend to a write against an external database like Postgres?
expertNo — that's the exact same dual-write problem from Chapter 15; Kafka transactions only cover atomicity across Kafka topics/partitions themselves, not an external system, which is why the Outbox Pattern (Chapter 18) exists as a separate solution for that boundary.
System Design with Transactions
Design the money-movement part of a UPI-like system. What pattern do you use, and why not a single distributed transaction?
advancedA saga (likely orchestrated by a central switch), because the two banks' ledgers are independent systems — a single cross-bank distributed transaction isn't realistic at that scale/ownership boundary; failures are handled via a compensating reversal credit.
How do you prevent overselling the last unit of a flash-sale item?
advancedPessimistic locking (SELECT FOR UPDATE) on the specific inventory row under high contention, backed by a database CHECK constraint (stock >= 0) as a final safety net.
Why is 2PC generally the wrong answer in a ride-sharing or e-commerce system design interview?
expertThese systems need high availability and independently scalable services; 2PC's blocking coordinator model directly works against both, and eventual consistency via Saga/Outbox is an acceptable, well-handled trade-off for this domain.
Production Engineering
What does "idle in transaction" mean, and why is it dangerous?
intermediateA transaction that's open but not actively running a query (e.g. waiting on external I/O) — it still holds locks and an MVCC snapshot the whole time, silently degrading concurrency for other transactions.
How would you debug a saga that appears stuck, spanning four microservices?
advancedUse a shared correlation/saga ID propagated through every event and log line, and query distributed tracing (or grep centralized logs) by that ID to reconstruct the full cross-service timeline.
What metric would give you the earliest warning that your Outbox relay is failing, before any consumer notices missing events?
expertOutbox table backlog size (unpublished row count) — a growing backlog is a leading indicator, visible before downstream services experience any missing-event symptoms.
Capstone — A Fault-Tolerant Order-Payment System
1. "What is a transaction? Give a real-world example." (30 seconds)
advancedShould reference Chapter 01's all-or-nothing definition and a concrete story (bank, ATM, flight).
2. "Explain ACID. Which property has no dedicated internal mechanism of its own?" (2 minutes)
advancedAll four letters, correctly — and specifically that Consistency (Chapter 03) is an emergent property, not a separate log/lock mechanism like the other three.
3. "Why does self-calling a @Transactional method from within the same class not work?" (2 minutes)
advancedThe AOP proxy mechanism (Chapter 10) — this refers to the raw object, bypassing the proxy's TransactionInterceptor.
4. "Design the payment flow for a food delivery app spanning Order, Payment, and Restaurant services. What pattern, and why not a distributed transaction?" (4 minutes)
advancedSaga (Chapter 17), with specific compensations named for each step, and a clear explanation of why 2PC (Chapter 16) is the wrong choice at this scale/availability requirement.
5. "How do you guarantee the 'order placed' event is never lost, even if Kafka is briefly down?" (90 seconds)
advancedOutbox Pattern with CDC (Chapter 18) — write to a local outbox table atomically with the order, relay independently.