Skip to main content
Two-Phase Commit Protocol

Track 4: Distributed Transactions

Maintaining data integrity across multiple nodes. Distributed transactions are the hardest problem in distributed systems that you actually have to solve in practice. Single-machine transactions are like making a bank transfer within one branch — the teller can see both accounts and lock them. Distributed transactions are like coordinating a transfer between two banks in different countries, over unreliable phone lines, where either bank might lose power mid-call.
Track Duration: 36-44 hours
Modules: 6
Key Topics: 2PC, 3PC, Saga, TCC, Distributed Locking

Module 16: ACID in Distributed Systems

Local vs Distributed Transactions

Isolation Levels in Distributed Systems

Lowest level - can read uncommitted changes from other transactions.Problem: Dirty reads
Rarely used in production.

Snapshot Isolation and Write Skew


Module 17: Two-Phase Commit (2PC)

The classic distributed transaction protocol. The analogy that makes 2PC click: imagine a wedding ceremony. Phase 1 is when the officiant asks each person “Do you take this person to be your spouse?” Both must say “I do” (vote YES). Phase 2 is when the officiant pronounces them married (COMMIT). The critical problem with 2PC maps perfectly: if the officiant faints after both say “I do” but before pronouncing them married, the couple is stuck — they cannot marry themselves (commit) and they cannot un-say “I do” (abort) without the officiant’s decision.

2PC State Machines

2PC Failure Scenarios

2PC in Practice


Module 18: Three-Phase Commit (3PC)

An attempt to solve 2PC’s blocking problem.

3PC vs 2PC


Module 19: Saga Pattern

This is the most practical approach for microservices. Know this well for interviews.
Saga Pattern - Choreography vs Orchestration

Saga Coordination Styles

Services communicate via events, no central coordinator.

Implementing Saga Orchestration

Saga Failure Handling

Saga Design Principles

19.1 Distributed Sagas: Orchestration vs Choreography Deep Dive

For Staff/Principal level design, the choice between Orchestration and Choreography is not just about “coupling,” but about Observability, Testability, and Operational Complexity.

The Operational Comparison

Advanced: Saga Isolation Levels

Sagas provide Atomicity, Consistency, and Durability (ACD), but they lack Isolation. This leads to three main anomalies:
  1. Lost Updates: Saga 1 and Saga 2 both update a record, and one overwrite’s the other’s work without seeing it.
  2. Dirty Reads: A client reads data from a Saga step that later gets compensated (rolled back).
  3. Fuzzy Reads: A client reads a record at the start of a Saga and sees a different value at the end, even if the Saga succeeded.

Countermeasures (The “Staff Level” Solution):

  • Semantic Lock: A “pending” flag on records being updated by a saga. Other transactions must check this flag before modifying.
  • Commutative Updates: Design operations so order doesn’t matter (e.g., account_balance += 100 instead of account_balance = new_value).
  • Pessimistic View: Reduce the “Dirty Read” risk by only making changes visible at the end of the saga (requires a staging table).
  • Reread Value: Before committing a final step, reread the initial values to ensure they haven’t changed (Optimistic concurrency).
Staff Tip: If your saga has more than 5 steps or involves more than 3 teams, Orchestration is almost always the correct choice for long-term maintainability. Choreography is better for simple, high-frequency pipelines where latency is the primary concern.

Module 20: TCC Pattern

Try-Confirm-Cancel - another distributed transaction pattern.

TCC vs Saga


Advanced Distributed Transactions

Google’s Percolator (Snapshot Isolation at Scale)

Percolator is the protocol Google uses for incremental processing of the web index, built on top of Bigtable. It provides ACID transactions using a Primary Lock and Secondary Locks pattern.

Distributed Deadlock Detection

In distributed systems, deadlocks can occur when nodes form a cycle of dependency across different machines.

Module 21: Distributed Locking

Coordinating access to shared resources across nodes.

The Problem

Redis Single-Node Lock

Redlock Algorithm

Distributed lock across multiple Redis nodes.

Redlock Critique (Martin Kleppmann)

Fencing Tokens

The solution to the GC pause problem.

Zookeeper-Based Locks


Key Interview Questions

2PC:
  • Coordinator blocks until all participants vote
  • Holds locks during prepare phase
  • Strong consistency, immediate
  • Can block on coordinator failure
  • Better for database transactions
Saga:
  • No global locks, each step commits independently
  • Uses compensation for rollback
  • Eventually consistent
  • No blocking, more available
  • Better for microservices, long transactions
When to use:
  • 2PC: Short transactions, need strong consistency, can afford latency
  • Saga: Long transactions, need high availability, can tolerate eventual consistency
Core challenges:
  1. Can’t distinguish slow from dead
    • Heartbeat timeout? Node might just be slow
    • GC pause, network delay, CPU starvation
  2. Clock skew
    • Lock expiry depends on time
    • Different machines have different times
    • NTP can jump clocks
  3. Partial failures
    • Acquired lock on some nodes, not others
    • Network partition mid-operation
  4. Client failures
    • Client crashes while holding lock
    • Need automatic expiry/release
    • But expiry can cause double-holding
Solutions:
  • Fencing tokens (best)
  • Consensus-based locks (Zookeeper, etcd)
  • Design system to tolerate inconsistency
  • Accept that “perfect” distributed lock doesn’t exist

Advanced Design Scenarios

Scenario 1: Global Bank Transfer System

You are designing a global bank transfer platform where money moves between accounts in different regions and possibly different underlying systems. Hard requirements:
  • No double-spend, no lost money
  • Transfers must be auditable and reversible
  • Transfers may cross currencies and regions
  • Short periods of unavailability are acceptable; inconsistency is not
Design outline:
  • Partition accounts into shards; each shard is a replicated log protected by Raft/Paxos
  • Within a shard, use strict serializable transactions (single-shard transfers are simple)
  • For cross-shard transfers, use either:
    • 2PC over consensus-backed shards (coordinator decisions are written via consensus), or
    • Transactional outbox + reconciliation if you can tolerate temporary imbalance
2PC-over-consensus pattern:
  • Each shard is internally replicated; coordinator is itself backed by consensus (no single-point-of-failure)
  • Steps:
    1. Begin transaction with a globally unique ID txid
    2. Phase 1 (prepare): write “prepare(txid, debit/credit)” to each shard’s replicated log and wait until committed
    3. Once all participants are prepared, coordinator writes “commit(txid)” to its own log and notifies shards
    4. Phase 2 (commit): each shard finalizes its local changes (e.g., move from “reserved” to “posted”)
  • If coordinator fails, replay logs to determine final outcome; log state is the source of truth
Interview talking points:
  • Why 2PC is blocking and how consensus for the coordinator removes single-point-of-failure but not all blocking
  • How you would replay after a crash to restore consistent state
  • Where you might deliberately relax consistency (e.g., showing “pending” vs “settled” balances on the UI)

Scenario 2: Microservices Order Workflow with Sagas

You run a microservices-based e-commerce platform with services for Orders, Payments, Inventory, and Shipping. Requirements:
  • High availability; cannot afford global locks or long-lived distributed transactions
  • Must support long-running workflows (shipping, warehouse operations)
  • Business rules are tolerant of temporary inconsistency as long as system eventually converges
Design:
  • Use Saga orchestration (one central orchestrator) to manage the order lifecycle
  • Each step is a local transaction with a compensating action
Example saga steps:
  1. Create order (status: PENDING)
  2. Reserve inventory for items
  3. Authorize payment
  4. Schedule shipment
Compensations:
  • If shipping fails: cancel shipment and release inventory, void payment or refund
  • If payment authorization fails: release inventory and mark order CANCELLED
Persistence and reliability:
  • Saga state (current step, payload, retries) stored in a durable saga log (e.g., its own table or topic)
  • Each local step must be idempotent; compensations must be idempotent as well
  • Use outbox pattern from each service to publish events reliably
Interview talking points:
  • Trade-offs vs 2PC (availability vs immediate consistency)
  • How to debug and replay a failed saga from the saga log
  • Handling compensation failures (DLQs, manual intervention, reconciliation jobs)

Scenario 3: TCC for High-Value Reservations

You are designing a hotel or flight booking system where overbooking is unacceptable and reservations are short- lived. Requirements:
  • Temporarily “hold” a room/seat while the user completes payment
  • If payment fails or times out, release the hold automatically
  • Stronger isolation than pure saga; must avoid double-booking
Design with TCC (Try-Confirm-Cancel):
  • TRY: reserve capacity in each system (rooms, seats, loyalty points) with a hold token and expiry
  • CONFIRM: commit all holds and make them permanent once payment succeeds
  • CANCEL: release holds if any TRY fails or payment fails/timeouts
Implementation details:
  • Each resource service exposes idempotent try, confirm, cancel endpoints keyed by reservationId
  • TRY operations must be side-effect-free beyond reserving capacity; they should not make changes visible to other users until CONFIRM
  • Store overall TCC state in a coordinator (which can itself be a saga orchestrator with TCC semantics)
Interview talking points:
  • When TCC is preferable to Saga (short-lived, strong isolation, reservable resources)
  • How to handle timeout of reservations (background job that auto-cancels stale TRY states)
  • Failure modes when CONFIRM or CANCEL messages are delayed and how idempotency plus retries mitigates them

Next Steps

Continue to Track 5: Data Systems at Scale

Learn about partitioning, distributed databases, and stream processing