A distributed lock coordinates clients, but it does not by itself guarantee that only the current owner can change a protected resource. A lease can expire while its former owner is paused; if that client later resumes and sends a delayed write, the resource may accept it unless it checks ownership independently. For correctness-sensitive work, use resource-enforced fencing or a transaction that covers the shared state—not merely a lock API.
What a distributed lock does—and what it does not
A distributed lock is coordination state shared by processes that cannot rely on one machine’s memory. It can help prevent clients from intentionally doing the same work at the same time, and a time-to-live (TTL) can let other clients proceed if an owner crashes.
Those benefits depend on the failure model and on what the protected resource enforces. A lock service can record that a lease has expired and grant a new one, but that state change does not reach back in time to cancel requests already sent by the previous owner. The resource—the database, object store, or other system being changed—is the final boundary for rejecting stale work.
Safety and liveness are separate design goals
Redis describes mutual exclusion as a safety property: ideally, only one client holds the lock at a time. It describes deadlock freedom and fault tolerance as liveness properties: clients should be able to make progress, including after failures. These are design criteria, not unconditional guarantees across every implementation or timing condition. A TTL can help a system recover from a crashed owner, while also creating an expiry boundary that a slow or paused owner may cross.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
How a lease can leave a stale client able to write
Consider two clients, A and B, coordinating through a lease:
- A acquires the lock and begins work.
- A is suspended, or its network requests are delayed, long enough for the lease to expire.
- The lock service allows B to acquire the lock. B performs a write to the protected resource.
- A resumes and sends a write it prepared while it still believed it owned the lock.
The lock service may have followed its configured TTL correctly. Yet the resource can see writes from both successive owners because it does not automatically know that A’s lease expired. A pause, delayed packet, or delayed request can separate the lock service’s ownership state from the work that eventually reaches the target.
Fencing tokens: make the resource reject stale owners
A fencing token is a value that increases strictly with each new lock acquisition. Every operation performed under the lock carries its token. The protected resource remembers the greatest token it has accepted and rejects a request carrying an older one. If A’s request arrives after B has acquired a newer token and written, the resource can refuse A’s stale request.
Rank #2
As Martin Kleppmann puts it in his 2016 article, “The fix for this problem is actually pretty simple: you need to include a fencing token with every write request to the storage service.” The important qualification is that the storage service must actually validate the token; adding a number to a request without resource-side enforcement does not provide fencing.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Tokens must be ordered: a new acquisition needs a token greater than earlier acquisitions.
- Every protected operation must carry the token: an untagged write bypasses the protection.
- The target must check and remember tokens: it must reject values older than the greatest one it has accepted.
Kleppmann discusses ZooKeeper transaction IDs or znode versions as possible token sources in the setup he describes. A token source and a resource-side check must work together; a lock service’s lease ownership alone is not a substitute.
Redis locks and the Redlock disagreement
Redis’s official “Distributed Locks with Redis” documentation describes a TTL-based locking pattern and Redlock, a multi-node design intended to be safer than a basic single-instance approach. Redis presents mutual exclusion, deadlock freedom, and majority-based fault tolerance as goals of the design. The client’s usable validity window matters: work that runs beyond it cannot rely on the lease as if it were still current.
Rank #3
Kleppmann’s 2016 analysis reaches a different conclusion for correctness-sensitive uses. He argues that Redlock depends on timing assumptions that can be broken by arbitrary process pauses, delayed packets, or clock behavior, and that it does not provide monotonically increasing fencing tokens. That is his critique, not a conclusion endorsed by the Redis documentation. The practical point is to decide whether the lock is only reducing duplicate effort or is being trusted to protect correctness when timing failures occur.
How to do distributed locking
- Define the consequence of overlap. Decide whether duplicate execution merely wastes resources or can corrupt shared state, charge twice, lose data, or trigger an irreversible side effect.
- Identify the protected resource. Specify which database rows, files, objects, or external actions must be serialized. A lock around one component does not automatically cover other systems the job calls.
- Choose the enforcement boundary. If a stale write would be harmful, use a resource-side fencing check or a transaction that covers the shared state and operation. Do not assume that having a lease means the external resource can distinguish current from former owners.
- Choose coordination based on failure requirements. Assess behavior during process pauses and network delays, availability when a quorum or majority is unavailable, operational complexity, and whether duplicate work can be made harmless.
- Make ownership operations explicit. For a best-effort Redis lock, use ownership-safe acquisition and release so one client does not release another client’s lock. Treat the lock as approximate under failures rather than as a correctness barrier.
- Test the failure sequence that matters. In particular, reason through an owner pause beyond lease expiry, a second acquisition and write, and the first owner’s delayed write arriving afterward. Confirm whether the actual target resource rejects the stale operation.
Choosing an alternative to a best-effort lock
The right option depends on where correctness is enforced, whether duplicate work is acceptable, and what the system must do when coordination becomes unavailable. The options below are not interchangeable guarantees.
| Approach | Stale-owner protection | Availability and trade-off | When to consider it |
|---|---|---|---|
| Best-effort Redis lock | TTL-based coordination does not itself stop a former owner’s delayed write. Add resource-side fencing if stale writes matter. | Redis documents a majority-based fault-tolerance goal for Redlock. Availability behavior under majority loss is not stated here (Redis documentation). | When the lock is an efficiency optimization and occasional overlapping work is tolerable. |
| Consensus-backed coordination such as etcd | Lease ownership alone does not guarantee control of an external resource. Pair it with resource-side token validation when needed. | etcd documents consensus-backed API guarantees and lease and lock primitives. Its failure guide says recovery from majority failure requires a majority of members to become available. | When consistent coordination state is needed and the system can account for quorum availability and the separate resource boundary. |
| Database transaction or resource-native serialization | Can protect correctness when the transaction or serialization mechanism covers the actual shared state and operation. | Transaction behavior beyond the covered state and operation is not stated here (Kleppmann’s article). External side effects are not automatically inside a database transaction. | When the critical work can be expressed against a resource with suitable transactional guarantees. |
| Idempotent work or queue-based serialization | Can make duplicate work harmless or serialize work through a narrower mechanism; guarantees depend on the implementation. | Comparative availability and complexity figures are not stated in the cited sources. | When retries are expected, duplicate effects can be prevented, or work can be claimed and processed through a queue or transactional pattern. |
Best-effort Redis coordination
Use a Redis lock when its main value is avoiding redundant work rather than preserving correctness at the target. Follow the ownership-safe acquisition and release pattern in Redis’s documentation. If duplicate work could cause damage, do not rely on a TTL alone: require the resource to reject stale owners or move the critical operation into a suitable transactional boundary.
Rank #4
Consensus-backed coordination with etcd
etcd documents API guarantees in terms of consensus commit and provides coordination primitives including leases and locks. These properties govern coordination state; they do not automatically make a separate storage service honor that state. If the resource is external to etcd, it still needs an enforcement mechanism such as checking ordered fencing tokens. Also account for the availability consequence of a majority failure: the etcd v3.5 failure guide says recovery requires a majority of members to become available.
Transactions, idempotency, and queues
Kleppmann recommends considering a database with reasonable transactional guarantees when correctness depends on the lock. The transaction must cover the shared state and operation whose consistency matters. If work also calls an external service, a database transaction does not automatically make that external side effect atomic; design that boundary separately.
Another question is whether a broad lock is needed at all. Idempotent operations can make retries or duplicate execution harmless when they are designed to do so. A queue or transactional work-claim pattern may serialize a narrower unit of work. These are alternatives to evaluate for the application’s failure modes, not universal replacements with guarantees independent of their implementation.
Further reading
For the Redis design and its stated goals, see Redis, “Distributed Locks with Redis” (live documentation, accessed October 4, 2026). For the critique and fencing-token argument, see Martin Kleppmann, “How to do distributed locking” (February 8, 2016). For coordination guarantees and failure behavior, see the etcd v3.4 “etcd API guarantees” documentation and the etcd v3.5 “etcd versus other key-value stores” and “Failure modes” documentation. Kleppmann’s article also points readers to Designing Data-Intensive Applications for broader distributed-systems treatment.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

