CodeWithYash
DSA
Spring Boot
System Design
Series
Articles
Leaderboard
Sign In

Subscribe to Newsletter

Get the latest articles, DSA sheets, and system design challenges delivered to your inbox.

<CODEWITHYASH/>

The ultimate sanctuary for software engineers seeking deep mastery of core technical principles.

Library

  • Articles
  • DSA Sheets
  • Roadmaps

Connect

  • GitHub
  • LinkedIn
  • About
  • Contact

Legal

  • Privacy
  • Terms
  • Support

© 2026 CodeWithYash Global Systems.

Status: OperationalVersion: 4.2.0
System Design
OverviewTheory lessonsHLDLLD
All SeriesSeries
Distributed Systems

System Design Series

0%

0 of 33 topics completed

Progress
Idempotency & Safe RetriesTheory
25 min
Time, Clocks & Ordering in Distributed SystemsTheory
25 min
Distributed Consensus: Raft & PaxosTheory
30 min
Distributed Locking & Monotonic FencingTheory
25 min
Distributed Transactions: 2PC, Saga & Transactional OutboxTheory
30 min
Disaster Recovery & Multi-Region TopologiesTheory
25 min
System DesignDistributed Systems Mechanics & ReliabilityDistributed Locking & Monotonic Fencing

Complex Systems · Phase 3: Distributed Mechanics

Distributed Locking & Monotonic Fencing

Investigate why distributed locks fail under GC pauses and network delays, examine the Kleppmann-Sanfilippo Redlock debate, and implement fencing tokens correctly.

Primary specification: How to do distributed locking (Martin Kleppmann)

Written & reviewed by Yash Patel 25 minBaseline 2026.1 Curated Blueprint· Verified 2026-09-14

Lesson 21 of 33

1d streak

The Architectural Question

A client acquires a distributed lock, enters a 30-second garbage collection pause during which the lock lease expires, and then awakens to corrupt shared storage.

Core Engineering Objectives

  • Why distributed locks are fragile: long Stop-the-World GC pauses, thread descheduling, and network delays
  • The Redlock controversy: Martin Kleppmann’s critique vs Salvatore Sanfilippo’s defense
  • The correct pattern: distributed lock leases paired with monotonically increasing fencing tokens validated at storage

Step 1: The Core Problem: Why Distributed Locks are Fundamentally Hazardous

In a single-process application, mutual exclusion is solved via operating system mutexes or CPU atomic instructions (CMPXCHG). The CPU hardware bus arbitration guarantees that only one thread enters the critical section. In a distributed system, there is no shared memory, no hardware bus, and no synchronized clock.

The Mirage of the Distributed Mutex

Engineers routinely assume that acquiring a distributed lock (e.g. from Redis or ZooKeeper) grants them an exclusive lease during which no other process can access the protected resource. In reality, distributed locks are leases subject to asynchronous network delays, operating system scheduling pauses, and garbage collection freezes. A client can acquire a lock, fall asleep, awaken after the lock has expired, and execute destructive writes under the false belief that it still owns the lock!

Without storage-enforced monotonic fencing tokens, a distributed lock provides only an illusion of safety, guaranteeing data corruption under ordinary production operating conditions.

Step 2: Requirements, Theoretical Bounds, and Kleppmann’s Dilemma

Martin Kleppmann (author of Designing Data-Intensive Applications) established the theoretical framework for distributed locks: you must explicitly categorize why you are locking.

Locking for Efficiency (Avoiding Redundant Work)

If the lock fails, the only consequence is duplicate computation (e.g. two workers process the same email or render the same image twice). Small race conditions do not corrupt data or lose money. A lightweight Redis lock is completely appropriate here.

Locking for Correctness (Data Integrity & Money)

If two workers execute concurrently, data is corrupted, inventory is double-allocated, or funds are double-spent. In this category, simple distributed locks are INSUFFICIENT without monotonic fencing tokens verified at the persistent storage layer.

Lease Time-to-Live (TTL)

To prevent deadlocks if a client crashes while holding a lock, distributed locks must have a finite TTL. However, TTL relies on physical time duration, which can be violated by GC pauses and VM descheduling.

Fencing Token

A monotonically increasing integer generated by the lock coordinator on every successful lock grant. Persistent storage validates this token on every write: if an incoming write carries a token smaller than the highest token committed so far, the write is rejected.

Locking TechnologyConsensus MechanismFailure ToleranceFencing Token SupportProduction Evaluation
Redis (Single Instance)None (single-threaded memory)Zero node failure toleranceNone (requires manual generation)Great for efficiency; unsafe for correctness
Redis Redlock (5 Instances)Independent majority quorumsTolerates 2 node crashesNone out-of-the-boxHighly controversial; vulnerable to clock jumps and GC pauses
Apache ZooKeeperZab atomic broadcast consensusStrict quorum (Tolerates (N-1)/2 crashes)Native via zxid / sequential znodesBattle-tested gold standard for distributed coordination
etcdRaft consensus algorithmStrict quorum (Tolerates (N-1)/2 crashes)Native via Raft revision numbersCloud-native gold standard; powers Kubernetes leases
Database Pessimistic LockRDBMS Row Lock (SELECT FOR UPDATE)Tolerates replica failover via ACID WALNative via AUTO_INCREMENT / MVCC versionSimplest & safest if all resources reside in the same database

Step 3: Naive Architecture: The Stop-the-World GC Annihilation

Consider the classic failure trace documented by Martin Kleppmann in his critique of the Redlock algorithm. Client 1 acquires a lock to write to an object store, but is halted by an unexpected operating system pause.

  1. 01Step 1: Lock Acquisition. Client 1 requests a lock on resource_customer_100 from Redis with a 10-second TTL. Redis successfully grants the lock.
  2. 02Step 2: The Stop-the-World Pause. Client 1’s JVM triggers a major Garbage Collection pause (or the OS deschedules the container during heavy memory swapping) lasting 15 seconds.
  3. 03Step 3: Lease Expiration. While Client 1 is frozen in GC, 10 seconds elapse. Redis automatically expires the lock lease on resource_customer_100 and frees the key.
  4. 04Step 4: Lock Re-grant. Client 2 requests a lock on resource_customer_100. Redis grants the lock to Client 2 with a fresh 10-second lease.
  5. 05Step 5: Client 2 Writes. Client 2 enters the critical section, writes version 2 of the customer record to storage, and safely releases the lock.
  6. 06Step 6: Client 1 Awakens & Corrupts Data. Client 1’s GC cycle completes. Client 1 resumes execution at the exact line of code following lock acquisition! Client 1 has no idea that 15 seconds have passed, believes it still owns the lock, and writes its stale version 1 data to storage, completely overwriting and destroying Client 2’s committed updates!

The Fatal Flaw: Checking `isLockHeld()` is Useless

A naive developer attempts to fix this by writing if (lock.isStillHeld()) { storage.write(); }. This check is completely ineffective! The process can pause for 15 seconds AFTER the if (lock.isStillHeld()) check passes, but BEFORE the network packet for storage.write() hits the socket buffer. Checking lock validity inside the client process is fundamentally prone to Time-of-Check to Time-of-Use (TOCTOU) race conditions.

Step 4: Evolved Production Architecture: Fencing Tokens & Storage Enforcement

To make distributed locks safe for correctness, mutual exclusion must be enforced by the storage layer using monotonically increasing Fencing Tokens.

snippet.typescripttypescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// PRODUCTION DISTRIBUTED LOCK WITH FENCING TOKEN & STORAGE VALIDATION
import { createHash, randomBytes } from 'crypto';

export interface FencedLockGrant {
  lockKey: string;
  lockToken: string;      // Unique random secret for safe release
  fencingToken: number;   // Monotonically increasing sequence number
  expiresAtMs: number;
}

export interface StorageRecord<T> {
  id: string;
  payload: T;
  lastFencingToken: number; // Highest fencing token committed
}

// 1. STORAGE LAYER: Monotonic Fencing Validator
export class FencedStorageEngine<T> {
  private records: Map<string, StorageRecord<T>> = new Map();

  // Storage validates fencing token on EVERY write
  public write(id: string, payload: T, clientFencingToken: number): { success: boolean; error?: string } {
    const existing = this.records.get(id);

    if (existing) {
      // INVARIANT: Reject any write carrying an older or equal fencing token!
      if (clientFencingToken <= existing.lastFencingToken) {
        return {
          success: false,
          error: `STALE_FENCING_TOKEN: Rejected token ${clientFencingToken}. Highest committed is ${existing.lastFencingToken}.`,
        };
      }
    }

    // Accept write and update highest committed fencing token
    this.records.set(id, {
      id,
      payload,
      lastFencingToken: clientFencingToken,
    });

    return { success: true };
  }

  public read(id: string): StorageRecord<T> | undefined {
    return this.records.get(id);
  }
}

// 2. COORDINATOR LAYER: Distributed Lock Manager with Atomic Monotonic Fencing Tokens
export class RedisDistributedLockManager {
  // CRITICAL DISTRIBUTED REALITY: Fencing tokens MUST be strictly monotonic and
  // generated server-side by the coordinator (e.g., Redis atomic INCR, ZooKeeper zxid,
  // or etcd cluster revision). A client-side memory counter clobbers across multiple app nodes.

  public async acquireLock(
    redisClient: any,
    resource: string,
    ttlMs: number
  ): Promise<FencedLockGrant | null> {
    const lockToken = randomBytes(16).toString('hex');
    const lockKey = `lock:${resource}`;
    const fencingCounterKey = `lock:fence:${resource}`;

    // Atomic acquisition & monotonic token assignment via Lua script:
    // 1. SET lockKey lockToken NX PX ttlMs
    // 2. If acquired, INCR fencingCounterKey and return token; else return nil
    const acquireLuaScript = `
      if redis.call("set", KEYS[1], ARGV[1], "NX", "PX", ARGV[2]) then
        local token = redis.call("incr", KEYS[2])
        return { ARGV[1], token }
      else
        return nil
      end
    `;

    const result = await redisClient.eval(acquireLuaScript, 2, lockKey, fencingCounterKey, lockToken, ttlMs);
    if (!result) return null;

    return {
      lockKey,
      lockToken: result[0],
      fencingToken: Number(result[1]),
      expiresAtMs: Date.now() + ttlMs,
    };
  }

  // ATOMIC RELEASE VIA LUA SCRIPT:
  // Must verify value matches lockToken before deleting to avoid releasing someone else's lock!
  public getReleaseLuaScript(): string {
    return `
      if redis.call("get", KEYS[1]) == ARGV[1] then
        return redis.call("del", KEYS[1])
      else
        return 0
      end
    `;
  }
}

Use it when

Always enforce monotonic fencing tokens in SQL (e.g. WHERE fencing_token > last_fencing_token) or object storage conditional writes whenever a distributed lock guards financial or non-idempotent state.

Reconsider when

Use lightweight Redis single-instance locks with TTL if the workload is strictly performance-oriented (e.g. preventing two background cron jobs from scraping the same weather API simultaneously).

Step 5: Step-by-Step Message Flow Trace: Fencing Token Rejection

  1. 01Step 1: Lock Grant to Client 1. Client 1 acquires lock on /order/101 from the coordinator. The coordinator issues Fencing Token 33 with a 10s TTL.
  2. 02Step 2: Client 1 GC Freeze. Client 1’s virtual machine pauses for 12 seconds due to host memory swapping. The 10s TTL expires in the coordinator.
  3. 03Step 3: Lock Grant to Client 2. Client 2 requests the lock on /order/101. The coordinator grants the lock and issues monotonically incremented Fencing Token 34.
  4. 04Step 4: Client 2 Commits with Token 34. Client 2 sends UPDATE orders SET status = "SHIPPED", fencing_token = 34 WHERE order_id = 101 AND 34 > fencing_token. The database verifies 34 > 0, commits the change, and stores lastFencingToken: 34.
  5. 05Step 5: Client 1 Awakens with Stale Token 33. Client 1 awakens from its GC pause. Believing it is still the legitimate lock owner, it transmits UPDATE orders SET status = "CANCELLED", fencing_token = 33 WHERE order_id = 101 AND 33 > fencing_token.
  6. 06Step 6: Database Storage Rejection. The database evaluates the atomic predicate: 33 > 34 evaluates to FALSE! The database rejects Client 1’s write with 0 rows affected. Client 2’s data remains pristine. Catastrophe averted!

Step 6: Real-World War Stories: GitHub, HBase, and the Redlock Debate

The Great Kleppmann vs. Antirez Redlock Debate (2016)

In 2016, Martin Kleppmann published a detailed analysis proving that the Redlock algorithm (which claims to provide fault-tolerant distributed locking across 5 independent Redis masters without consensus) is fundamentally unsafe. Kleppmann proved that Redlock relies on dangerous assumptions: synchronized physical clocks, bounded network delays, and bounded execution times. Salvatore Sanfilippo (antirez, creator of Redis) wrote a passionate defense. The distributed systems community concluded: for efficiency, Redlock is unnecessarily heavy; for correctness, Redlock is unsafe because it cannot generate monotonic fencing tokens without a consensus protocol like Raft or Paxos.

GitHub: The 2016 Redis Failover Lock Loss

GitHub used Redis to coordinate distributed background workers. When a primary Redis node experienced a transient network glitch, GitHub’s automated orchestrator promoted a replica to master. Because Redis master-replica replication is asynchronous, several distributed lock keys that had been granted on the old master had not yet been replicated to the replica. The new master immediately granted those same locks to other workers, resulting in concurrent execution that corrupted database migration scripts and took GitHub offline for hours.

Apache HBase: HMaster Failover via ZooKeeper Ephemeral Nodes

Apache HBase relies on Apache ZooKeeper to manage its primary HMaster coordinator. If an active HMaster freezes during a major Java CMS GC pause, ZooKeeper’s session timeout triggers, automatically deleting the HMaster’s ephemeral znode. A backup HMaster watching that znode detects the deletion, promotes itself to active, and takes over the cluster. To prevent the paused HMaster from waking up and executing split-brain commands, HBase writes the ZooKeeper zxid fencing token to HDFS, instantly terminating any stale commands from the deposed master.

Step 7: Hard Trade-Offs Matrix: Distributed Lock Topologies

TechnologyAcquisition LatencyConsensus Backed?Automatic Deadlock RecoveryFencing SupportOperational Complexity
Redis SET NX PX~1 ms (in-memory)No (single node or async replica)TTL expirationNone (manual token generation)Extremely low; single Redis instance
Redis Redlock~5 – 15 ms (5 nodes)Pseudo-quorum (no log replication)TTL expirationNone out-of-the-boxHigh; must maintain 5 independent Redis instances
Apache ZooKeeper~5 – 20 ms (fsync)Yes (Zab atomic broadcast)Ephemeral znode session dropNative (zxid / sequential znode index)High; complex JVM operational footprint
HashiCorp Consul / etcd~5 – 15 ms (fsync)Yes (Raft consensus)Session lease TTL + keepaliveNative (Raft 64-bit revision index)Moderate; single Go binary with simple operations
Postgres Advisory Lock~2 – 5 ms (WAL)Yes (Postgres master-replica)Transaction end or connection closeNative (transaction IDs / sequences)Zero if already running PostgreSQL

Architectural Boundary · Do Not Confuse

Concept A

Redis Ephemeral TTL Lock

Concept B

ZooKeeper Ephemeral Sequential Lock

Redis locks rely on time elapsed (TTL). If a client is delayed, the lock silently disappears from under its feet without notification. ZooKeeper locks rely on active TCP heartbeat sessions: when a client crashes, its session expires and ZooKeeper removes the ephemeral znode. Furthermore, ZooKeeper provides the "Curator Lock Recipe": clients create sequential znodes and watch only their immediate predecessor, completely eliminating thundering herd stampedes when thousands of workers wait for the same lock.

Step 8: Failure Modes, Edge Cases & Cascading Outages

  1. 01The Accidental Lock Release Catastrophe: Client A acquires a lock with a 5s TTL. Due to a slow SQL query, Client A takes 7 seconds. At 5 seconds, Redis expires the lock. Client B acquires the lock. At 7 seconds, Client A finishes and blindly executes redis.del("lock_key")! Client A has just deleted Client B’s valid lock! Now Client C acquires the lock, resulting in two active workers. Solution: Always release locks via Lua script matching a unique secret token.
  2. 02The Clock Jump Acceleration Bug: In Redlock, if 3 out of 5 Redis servers have their physical NTP clocks adjusted forward by 10 seconds, keys with a 5s TTL expire immediately. A client that just acquired the lock loses it within milliseconds, leading to multiple clients entering the critical section simultaneously.
  3. 03Thundering Herd on Lock Release: 500 workers attempt to acquire the same lock in Redis via polling loops. When the lock owner releases it, all 500 workers hammer Redis with SET NX within 1ms, saturating Redis CPU and network buffers. Solution: Use ZooKeeper/etcd watches where only the next sequential waiter is notified.

Step 9: Interviewer Deep-Dive Gauntlet (Staff/Principal Level)

Deep-Dive Q1: Why is releasing a Redis distributed lock with a simple `DEL` command a critical architectural bug, and how does a Lua script fix it?

Model Answer: If Client A acquires a lock with a 10s TTL, experiences an unexpected 12s delay, and then issues DEL lock_key, it is unaware that its lease already expired at 10s. During the 2-second gap, Client B requested and was granted the lock. When Client A executes DEL, it inadvertently deletes Client B’s legitimate lock! Client C can now immediately acquire the lock, resulting in Client B and Client C operating concurrently in the critical section. To fix this, Client A must generate a cryptographically random unique value (e.g. UUIDv4) upon acquisition. Releasing the lock requires an atomic Lua script: if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end. This guarantees that a client can delete the lock ONLY if the stored value still matches its unique token.

Deep-Dive Q2: How does ZooKeeper’s Ephemeral Sequential znode recipe completely eliminate the "thundering herd" problem when 5,000 clients contend for the same lock?

Model Answer: In a naive locking system, when a lock is released, all waiting clients are notified, causing thousands of threads to race to acquire the lock simultaneously. ZooKeeper avoids this with its recipe: 1) A client wanting the lock creates an ephemeral sequential znode: /locks/resource/lock-0000000001, lock-0000000002, etc. 2) The client queries all children of /locks/resource. 3) If the client’s znode has the lowest sequence number, it holds the lock! 4) If it does not have the lowest number, it does NOT watch the lock itself; it sets an asynchronous watch ONLY on the znode with the immediate predecessor sequence number. 5) When Client 1 releases its lock (or crashes), only Client 2 receives a watch notification. The remaining 4,998 clients receive zero notifications and emit zero network traffic, achieving O(1) message overhead per lock handover.

Deep-Dive Q3: If shared storage must enforce monotonic fencing tokens anyway, why do we even need a distributed lock manager in the first place?

Model Answer: This is the fundamental insight of Martin Kleppmann’s thesis. If shared storage can reject stale writes via WHERE fencing_token > last_fencing_token, you might ask: why not dispense with the lock manager entirely? The answer is Efficiency and Resource Protection. While the fencing token guarantees Correctness at the final write step, acquiring a lock allows the system to avoid executing millions of CPU cycles, heavy image processing, expensive database reads, or third-party API calls that would ultimately be discarded anyway. The distributed lock acts as an efficient optimistic traffic filter to serialize execution, while the storage fencing token acts as the infallible cryptographic safety net.

Deep-Dive Q4: Under what conditions does an asynchronous Redis master-replica setup fail to guarantee mutual exclusion even when using correct Lua scripts and UUIDs?

Model Answer: Redis replication is asynchronous by design to achieve sub-millisecond latencies. When Client A executes SET lock_key uuid NX PX 10000, the write is acknowledged as soon as it hits the master’s in-memory data structures. Before that write command is replicated to the async replica, the master hardware crashes. Sentinel or Redis Cluster detects the master failure and promotes the replica to master. Because the replica never received the lock write, lock_key does not exist on the new master. Client B requests the lock, and the new master immediately grants it. Both Client A and Client B now hold the lock simultaneously, completely violating mutual exclusion.

Step 10: Active Recall & Verification Checkpoint

Active Recall Checkpoint

Why does checking if (lock.isValid()) immediately before writing to a database fail to prevent split-brain write corruption?

Hint: Think about Time-of-Check to Time-of-Use (TOCTOU) and garbage collection pauses.

Show answer & explanation

Because an operating system process pause, garbage collection freeze, or network socket stall can occur immediately AFTER the if (lock.isValid()) evaluation passes, but before the database write packet is transmitted. By the time the write arrives at the database, the lock has expired and been granted to another node. The storage engine itself must validate a monotonic fencing token atomically with the write.

Active Recall Checkpoint

What is the purpose of an ephemeral node in ZooKeeper or a lease keep-alive in etcd?

Hint: What happens when a client process crashes without executing its cleanup code?

Show answer & explanation

An ephemeral node exists only as long as the client maintains an active heartbeat session with the ZooKeeper cluster. If the client crashes, is killed, or is partitioned away, the session times out and ZooKeeper automatically deletes the ephemeral node, releasing the lock and preventing catastrophic cluster deadlocks.

Production Postmortem & Verification

Production Incident Postmortem

  1. Trigger / Setup: Client 1 acquires a Redis lock with a 10s TTL, pauses for 15s during a full GC cycle, while Client 2 acquires the expired lock.
  2. Production Symptom: Both Client 1 and Client 2 simultaneously write conflicting data to shared storage, corrupting customer state.
  3. Root Cause & Fix: A lock lease cannot guarantee mutual exclusion without storage-enforced monotonic fencing tokens that reject stale write attempts.

Acceptance Criteria & Outcomes

  • Diagram how GC pauses and network delays invalidate lock exclusivity assumptions.
  • Explain the mechanism of monotonic fencing tokens and why storage-level validation is mandatory.
  • Evaluate consensus-backed locks (ZooKeeper/etcd ephemeral nodes) versus memory-backed locks (Redis).

End-of-Chapter Synthesis & Key Takeaway

Distributed Locking & Monotonic Fencing is built around one fundamental rule: Establish clear responsibility and explicit trade-offs.. Before adding components, establish explicit quantitative SLAs for latency, throughput, and consistency. Choose the simplest architecture that meets stated constraints.

Architectural & Technical Interview Review

Core FAANG Interview Questions

3 Questions
Q01
How do you justify introducing Distributed Locking & Monotonic Fencing into a high-scale production architecture?
Click to reveal model answer →Hide answer ↑Requirements & Design Brief

Introduce Distributed Locking & Monotonic Fencing only when measured scale, data size, or failure boundaries exceed single-node capacity. State the exact bottleneck, evaluate operational overhead, and verify that the trade-offs justify the added moving parts.

Source section: Requirements & Design Brief
Q02
What is the primary trade-off and hidden operational cost of Distributed Locking & Monotonic Fencing?
Click to reveal model answer →Hide answer ↑Architecture Trade-offs

It improves scalability and availability, but introduces network hops, serialization overhead, and eventual consistency or coordination complexity.

Source section: Architecture Trade-offs
Q03
How do you handle catastrophic failure or dependency degradation in Distributed Locking & Monotonic Fencing?
Click to reveal model answer →Hide answer ↑Failure Review & Recovery

Implement connect/read timeouts, exponential backoff with jitter, and fallback defaults so downstream degradations do not cause cascading outages.

Source section: Failure Review & Recovery

Production Pitfalls & Anti-Patterns

Critical Failure Anti-Patterns

!

Premature Distributed Complexity

Scattering distributed components before identifying concrete write, read, or storage limits creates accidental points of failure and operational debt.

Production Mitigation: Start with the simplest modular design that satisfies requirements, evolving it only as measured constraints dictate.

!

Unbounded Retries and Cascading Storms

When a dependency degrades, immediate synchronized retries multiply downstream traffic, turning a minor slowdown into a total fleet outage.

Production Mitigation: Enforce strict retry budgets, exponential backoff, and full randomized jitter on all client calls.

!

Neglecting Observability and Metrics

Deploying architecture without distributed tracing or p99 tail latency alerts leaves engineers blind when partial partitions occur.

Production Mitigation: Export metrics for request rate, error rate, p95/p99 duration, and saturation at every service boundary.

Primary Documentation & Specifications

How to do distributed locking (Martin Kleppmann)
Previous LessonDistributed Consensus: Raft & PaxosDistributed MechanicsNext LessonDistributed Transactions: 2PC, Saga & Transactional OutboxDistributed Mechanics

In this chapter

01Architectural Question02Step 1: The Core Problem: Why Distributed Locks are Fundamentally Hazardous03Step 2: Requirements, Theoretical Bounds, and Kleppmann’s Dilemma04Step 3: Naive Architecture: The Stop-the-World GC Annihilation05Step 4: Evolved Production Architecture: Fencing Tokens & Storage Enforcement06Step 5: Step-by-Step Message Flow Trace: Fencing Token Rejection07Step 6: Real-World War Stories: GitHub, HBase, and the Redlock Debate08Step 7: Hard Trade-Offs Matrix: Distributed Lock Topologies09Step 8: Failure Modes, Edge Cases & Cascading Outages10Step 9: Interviewer Deep-Dive Gauntlet (Staff/Principal Level)11Step 10: Active Recall & Verification Checkpoint12Production Verification13Synthesis & Review14Primary References

Chapter promise

Why distributed locks are fragile: long Stop-the-World GC pauses, thread descheduling, and network delays