An outbox claim grants one worker a bounded chance to process an event; the claim token identifies the worker allowed to acknowledge it.
Spring outbox claims: lease expiry and token-fenced acknowledgement
Reject the stale worker
The H2 update takes a PENDING row only when it is due and its current lease is absent or expired. Worker A claims at logical time 100 until 120. At 120 its acknowledgement fails; worker B reclaims the row. A second acknowledgement from A still fails because the token no longer matches. B can acknowledge before its own lease expires.
One conditional UPDATE makes the state check and mutation a single database statement. The earlier lease fixture covers a smaller claim boundary. The relay test adds the due-time predicate and requires an unexpired lease for acknowledgement.
Where fencing stops
The token fences only this outbox row. If A publishes to a broker just before or after its lease expires, the database cannot undo that publish. A downstream event-ID ledger still has to reject a repeat. The fixture runs sequentially: H2 behavior here says nothing about lock contention, SKIP LOCKED, isolation levels, or throughput on the target database.
Lease length must exceed normal processing time or support renewal with a checked owner token. An unbounded lease can strand work; a very short lease causes avoidable duplicates. Measure actual processing latency and recovery goals before choosing it.
Checked source
update delivery_outbox set claim_token = ?, lease_until = ?
where event_id = ? and status = 'PENDING' and next_attempt_at <= ?
and (claim_token is null or lease_until <= ?);Verification boundary
OutboxRelayFlowTest has seven local tests in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete test.
Costs and limits
Logical timestamps make the test deterministic. The model does not account for clock skew across machines or an external publish that finishes after the lease expires.
Common Mistakes
- Do not acknowledge using only the event ID.
- Do not count a lease as a distributed lock on external systems.
- Do not infer concurrent claim safety from sequential H2 tests.
Read next
Spring outbox relay: claim, deliver, and acknowledge one event, Spring consumer idempotency: reserve an event ID with the stock mutation, Spring outbox claims: allow recovery after a worker lease expires, Spring outbox retries: due time, delay cap, and attempt accounting.
Continue with lease race checks
Continue with Spring outbox claim race: one conditional UPDATE wins, Spring outbox lease renewal: extend only the current owner.
