Capstone — A Fault-Tolerant Order-Payment System
Every chapter built or hardened one piece. Here is the whole book, assembled into one system — plus a final cheat sheet and mock-interview script to run yourself through before the real thing.
Every pattern covered so far, composed: local ACID transactions per service, Outbox+CDC for reliable event publishing, Kafka's exactly-once semantics for delivery, an orchestrated Saga tying it all together with compensation, and locking/constraints protecting the hottest, highest-contention data.
| Capability | Chapters |
|---|---|
| Explain ACID from first principles, with the internal mechanism behind each letter | 02–05 |
| Choose the correct SQL isolation level for a given operation, and name every anomaly it prevents | 04 |
| Debug a real deadlock and fix its actual root cause, not just add retry logic | 07, 21 |
| Explain exactly why self-invoked @Transactional calls silently don't work, and fix it three ways | 10 |
| Choose the correct propagation type for a given call chain, including REQUIRES_NEW vs. NESTED | 09 |
| Explain Hibernate's dirty checking and persistence context without hand-waving | 12, 13 |
| Know precisely when MongoDB needs a real transaction, and when single-document atomicity already suffices | 14 |
| Design a Saga with correct compensation ordering for a multi-service business flow | 15–17 |
| Solve the dual-write problem with Outbox + CDC, and explain why polling alone isn't enough | 18 |
| Explain Kafka's exactly-once semantics precisely, including what it does NOT cover | 19 |
| Walk through UPI, inventory, ride-sharing, and insurance system designs with the right patterns | 20 |
| Monitor, trace, and debug transaction problems in a real production incident | 21 |
Nine questions, roughly in the order a real interview escalates them — say your answer out loud (or write it down) before looking at which chapter it maps to. If you can't answer one cleanly, that's your revision list, not a failure.
- "What's the difference between ACID Consistency and CAP Consistency?" — a strong answer names the actual scope difference (single-database constraints vs. cross-replica freshness) and gives one example of each, not just the acronym expansion. (Chapter 03)
- "I have
@Transactional public void foo() { this.bar(); }wherebar()is also@Transactional. Doesbar()get its own transaction?" — a strong answer explains the AOP-proxy mechanism and why self-invocation bypasses it, not just "no." (Chapter 10) - "Why does Spring not roll back on a checked exception by default?" — a strong answer states the default rule precisely (unchecked + Error roll back, checked exceptions don't) and how to override it with
rollbackFor. (Chapter 08) - "Walk me through what happens, step by step, when two transactions deadlock in Postgres." — a strong answer covers the wait-for graph, the background detector, and that the database picks a victim and rolls it back automatically — not just "it throws an error." (Chapter 07)
- "When would you choose optimistic locking over pessimistic locking?" — a strong answer reasons from conflict rate and cost of retry, with a concrete example on each side (flash sale vs. typical CRUD update). (Chapter 07)
- "Does MongoDB support transactions?" — a strong answer rejects the yes/no framing: single-document atomicity has always existed; multi-document ACID transactions exist since 4.0/4.2 and require a replica set; and MongoDB's own guidance is to reach for them rarely. A weak answer just says "yes" or "no." (Chapter 14)
- "Why can't you just wrap two microservices' database calls in one
@Transactionalmethod?" — a strong answer explains that each service owns its own database/connection, so there's no single ACID transaction spanning both, which is exactly the setup for 2PC vs. Saga. (Chapter 15) - "Compare Two-Phase Commit and the Saga pattern." — a strong answer covers strong-but-blocking-and-a-SPOF vs. available-but-eventually-consistent-and-needs-compensation, plus at least one real situation where 2PC is still the right call (Chapter 16's table). A weak answer just says "2PC is old, use Saga." (Chapters 16–17)
- "How do you guarantee a database write and a Kafka publish happen together?" — a strong answer names the dual-write problem by name, then describes the Outbox Pattern plus CDC (not just "write to both," which is the bug, not the fix). (Chapter 18)
▲ Common mistake
Reciting a definition is not the same as answering the question. Every one of these lands better with a one-sentence concrete example attached — an interviewer is listening for whether you've actually used the idea, not whether you've memorized Chapter 02's callout box.
| Concept | One-line recall |
|---|---|
| ACID | All-or-nothing (A), valid state (C), concurrent correctness (I), survives a crash (D). |
| Isolation anomalies | Dirty = uncommitted; Non-repeatable = same row changes; Phantom = new rows appear. |
| Optimistic vs. pessimistic | Optimistic = check at the end; Pessimistic = lock at the start. |
| MVCC | Multiple row versions — readers never block writers. |
| Propagation defaults | REQUIRED = join/share; REQUIRES_NEW = independent; NESTED = SAVEPOINT, not a real second transaction. |
| Self-invocation trap | this.method() skips the AOP proxy — no transaction. |
| Dirty checking | Hibernate compares current state vs. loaded snapshot at flush — no save() needed. |
| 2PC vs. Saga | 2PC = strong but blocking; Saga = available but eventually consistent, needs compensation. |
| Outbox Pattern | Write the event locally, atomically, with the business change — relay separately. |
| Kafka EOS | Idempotent producer (no duplicate sends) + transactions (atomic multi-partition writes) + read_committed on the consumer. |
◆ Beyond the core curriculum
Suggested extensions past what's covered here: Implement a full Saga state machine — persist each saga's current step durably (not just in memory), so an orchestrator crash mid-saga can resume exactly where it left off. Add distributed tracing for real — wire up OpenTelemetry across every service in the capstone diagram, correlated by the saga ID from Chapter 21 §4, and view a real multi-service trace end to end. Chaos-test your compensations — deliberately kill the Payment service mid-transaction in a staging environment and confirm the Order service's compensation actually fires correctly, rather than trusting the code path was ever really exercised. Explore the Saga vs. TCC (Try-Confirm/Cancel) pattern — a more structured alternative to free-form compensating transactions, common in some payment-industry architectures.
Want a visual for this concept?
Generate a diagram tailored to “Capstone — A Fault-Tolerant Order-Payment System” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →