I use fencing tokens when a lock alone is not enough. A paused process can wake up and still believe it owns the resource, so I recommend giving every owner a token that downstream systems can compare.
The resource must enforce ownership
The useful question is what the system does when the network stops being polite.
A lock service can issue token 17 to one worker and token 18 to the next worker. The storage layer accepts writes only from the highest valid token it has seen. That way, the old worker cannot corrupt state after it wakes up.
Lease example
The point here is to move from concept to operation: who uses it, what breaks, and what decision changes.
A job runner writes reports to shared storage. Worker A pauses after receiving token 17. Worker B receives token 18 and starts writing. When Worker A wakes up, storage rejects token 17.
Fenced write code
The code needs to answer the operational question: do we allow it, block it, retry it, or ask a human?
The shared resource rejects stale owners by comparing tokens:
void writeReport(long token, Report report) {
if (token < highestTokenSeen.get()) {
throw new StaleOwnerException();
}
highestTokenSeen.set(token);
storage.save(report);
}
The write is allowed only when the token is at least as new as the highest token already seen. That prevents an old leader from writing after a newer owner took over.
Sequence diagram: reject the stale owner
The important enforcement happens at the shared resource, not only at the lock service.
The safety check
- Use monotonically increasing tokens for exclusive ownership.
- Make downstream resources validate the token.
- Treat long pauses as normal, not as impossible.