A distributed lock can expire while the code that acquired it is still running. Another instance takes ownership, finishes its work and saves the result. Then the original instance resumes and overwri

Markdown supported · ⌘↵ to post
Good distinction between fencing for safety and lease expiry for liveness. If the protected operation sends a result to a queue or external service after the database write, would you carry the generation to that final receiver and reject stale deliveries there too? I work in marketing at BOMTOBE, makers of orke; this is a design question, not a claim that I tested this implementation.
One thing worth adding for anyone adopting this: count rejected publications by cause. Zero rows because Generation moved means another worker took over, which is the design working. Zero rows with Generation unchanged means only the lease time ran out, so builds are outliving the lease and its length or renewal needs attention. The UPDATE alone cannot tell the two apart, so a follow-up read of the row is needed to log which one happened. Did you consider returning the reason from the adapter instead of a bool?
I think the publish statement can drop AND LeaseUntilUtc > SYSUTCDATETIME() without losing safety, because the generation already fences the write. If nobody acquired after the lease ran out, Generation still matches and LeaseOwner is still the same worker, so the late write can't overwrite anyone. If someone did acquire, Generation has moved and the update matches zero rows either way. As written, a build that takes 31 seconds with no competing worker throws its result away, which is exactly the case the missing renewal loop would have to cover.
Kleppmann's 2016 locking post draws the same line: safety shouldn't rest on timing, and timeouts belong to liveness. Here the lease decides when another worker may take over, and the generation decides whose write counts. If you want a cap on how old a published report can be, I'd keep that as a separate freshness rule rather than part of the fence.
Darius Tran
Share thoughts and experience with other developers and product makers
The point that a longer expiry only delays the failure is the part people skip. The stale writer has no idea it lost the lease, so only the destination can refuse it.
The same thing shows up with agents that retry tool calls. A paused or timed-out run wakes up and writes after a newer run already did.
For side effects the database can't fence, like an email or a payment call, do you lean on idempotency keys with the provider, or an outbox so only the current owner ever sends?