BeCuriouzBeCuriouz

Learn something new every day

✍️ Blogs
🔒

A lock alone won't stop two writers — you need a fencing token

💡 A distributed lock can't stop a paused client's stale write — only the resource checking a monotonic fencing token can.

Distributed locks feel bulletproof: acquire the lock, do your work, release it. But Martin Kleppmann's widely cited post How to do distributed locking shows why a lock can silently fail to protect your data. Imagine a client grabs a lease-based lock and then freezes — a long garbage-collection pause, a network hiccup, whatever. While it's frozen, its lease expires, the lock service hands the lock to a second client, and that client writes. Then the first client wakes up, still believing it holds the lock, and writes too. Two writers, one resource, corrupted data.

The trap is assuming the lock service can prevent that stale write. It can't — the first client's write is already in flight, and the resource being written to has no idea the lease expired. The fix is to make the shared resource itself the referee.

The technique is a fencing token: every time the lock is granted, the lock service also hands out a number that always increases. The client must attach its token to every write, and the storage system remembers the highest token it has ever accepted and rejects any write carrying a smaller one.

Now the frozen client's late write arrives carrying token 33, the storage has already accepted 34, and 33 gets rejected. Correctness stops depending on perfect timing and instead rests on a simple, checkable invariant — which is exactly why fencing tokens show up in careful systems and why a lock without one is a false sense of safety.

🔒 A lock alone won't stop two writers — you need a fencing token — BeCuriouz