Locks and Leases
Use a durable <lock> when two workflow runs must not change the same resource at once. WOML keeps a FIFO wait queue, renews the current lease, and issues a larger fencing token when ownership changes. Waiting releases the script worker.
Protect a multi-step operation
Place the lock inside <steps> after the step that identifies the resource:
<lock id="deployment" key="production/{{context.steps.plan.service}}" acquire-timeout="15m" lease="45s">
<step id="deploy">
<script>
return {
service: context.steps.plan.service,
fencingToken: context.lock.fencingToken
};
</script>
</step>
<step id="verify">
<script>return { healthy: true };</script>
</step>
</lock>Runs with the same key are serialized; different keys can proceed independently. Do not put secrets or raw payloads in a lock key. Pass the fencing token to an external system that supports fencing: a lease alone cannot stop an old process from writing after it loses ownership.
Choose the right scope
For one short critical section within a script, use services.locks.withLease(). Its callback is not a durable JavaScript closure. Use markup <lock> for several steps, restart recovery, or a wait or approval inside the protected scope.
Cancellation, timeout, failure, and restart preserve the durable ownership rules. Inspect a run before operating on a stuck resource:
woml get <run-id>