How Redis Distributed Locks Work
A practical explanation of Redis distributed locking, Redlock, fencing tokens, and the failure modes that show up in production.
A distributed lock is a way for multiple processes to agree that only one of them may enter a critical section. Redis is a common place to put that lock because it is fast, widely deployed, and supports atomic compare-and-set operations.
The difficulty is not acquiring a key. The difficulty is remaining correct when packets are delayed, a process pauses, or a node thinks it still owns a lock that Redis has already expired.
The simplest Redis lock
The core primitive is SET with NX and an expiry:
SET lock:orders NX PX 10000
NX means “set only if the key does not exist.” PX attaches a time-to-live so the lock cannot live forever if the owner crashes.
Release should be ownership-safe. A naive DEL is wrong if another client has already taken the lock after expiry. The usual pattern is a Lua script that deletes the key only when the value matches a unique token:
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
That token is typically a UUID generated by the client before acquire.
Why expiry exists
Without a TTL, a crashed owner leaves the system stuck. With a TTL, you introduce a new hazard: the owner may still be working after Redis expires the key.
That is the central trade-off:
- Too short a TTL and healthy work gets interrupted.
- Too long a TTL and a crash blocks the cluster.
A heartbeat that extends the TTL (PEXPIRE) helps, but it does not remove the pause problem. A garbage-collected runtime can freeze for longer than your TTL. A network partition can delay the unlock.
Single-instance Redis is not enough for some designs
If you only talk to one Redis primary, the lock is only as available as that primary. During failover, a replica that had not received the SET can become primary. Two clients can then believe they hold the lock.
This is why people discuss Redlock: acquire the lock on a majority of independent Redis nodes, using roughly the same token and a short clock window.
Redlock is controversial. It can reduce some failover races, but it still depends on timing assumptions. If you need a lock to protect correctness rather than efficiency, Redis may be the wrong tool.
Use a Redis lock to avoid duplicate work. Do not use it as the only fence around money movement, unique inventory, or any operation that cannot be made idempotent.
Fencing tokens
A more robust pattern is a monotonically increasing token. ZooKeeper and etcd can give you this naturally. With Redis you can approximate it by storing a version and requiring every write to carry that version.
The storage layer then rejects stale writers:
UPDATE inventory
SET quantity = quantity - 1, lock_token = 42
WHERE sku = 'abc' AND lock_token = 41;
If the original lock holder wakes up late, its write does not land. The lock no longer has to be perfectly exclusive at every instant; the data plane enforces a happens-before.
Practical guidance
- Prefer idempotent jobs. A lock then becomes an optimization.
- Always set a TTL and a unique owner token.
- Unlock with a compare-and-delete script, never a bare
DEL. - If correctness matters, add a fencing token in the database or queue.
- Measure pause times in your runtime before you pick a TTL.
Redis locks are simple to demo and subtle to operate. Treat them as a lease, not as a mutex from a textbook on shared-memory threads.
Related articles
- System Design Interview: Designing a Rate Limiter
A complete rate limiter design: algorithms, Redis implementations, distributed coordination, and the interview trade-offs that matter.
- How a URL Shortener Works
System design for a URL shortener: encoding, storage, redirects, caching, and the abuse problems that appear at real traffic.
- Designing a URL Shortener: Everything I Learned After Reading a Dozen Articles and Failing This Question Once
My personal notes on the classic 'design a URL shortener' interview question — the parts every article agrees on, the parts they don't, and the follow-up questions that actually got asked to me.