Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring outbox claims: allow recovery after a worker lease expires

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

An expiring outbox lease lets another worker reclaim a pending event after the current worker stops making progress.

Download Spring source kit

Claim with one conditional write

The H2 fixture writes an event E-41, then lets worker-A claim it until logical time 200. Worker-B cannot claim at time 150. At 200 it can replace the expired token. The SQL update checks state and lease time in the same statement, so the returned row count tells the caller whether it owns the row in this fixture. The earlier claim-state lesson checks a simple pending-to-claimed transition without expiry.

Use a database clock or an agreed clock policy in a real service. The fixture passes deterministic long values so the boundary is testable. It does not prove behavior under clock skew, a long network pause, database lock contention or a two-node race. Keep the claim transaction short; do not hold a row lock while calling a broker.

An expiry is not a cancellation

Worker-A may still be sending after its lease expires. Its send can race worker-B's retry. A lease permits recovery; it does not enforce exactly-once external delivery. A token-checked acknowledgement stops an old worker from marking the new owner's row done, and a consumer ledger handles repeated event IDs at the destination.

Checked source

sql
update delivery_outbox
set claim_token = ?, lease_until = ?
where event_id = ? and delivered = false
  and (claim_token is null or lease_until <= ?);

Verification boundary

OutboxLeaseContractTest.expiredLeaseCanBeReclaimedButOldWorkerCannotAcknowledge runs in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete tests.

Costs and limits

The check uses one row and sequential statements on H2. Each scan or update costs database I/O; an index and target-database query plan are needed for a large pending set. The test does not establish concurrent fairness, crash recovery across processes or broker delivery.

Common Mistakes

  • Do not interpret lease expiry as proof the former worker has stopped.
  • Do not hold a database transaction open during network delivery.
  • Do not assume test-supplied timestamps cover production clock behavior.

Read next

Spring outbox claims: move pending work once per database state, Outbox acknowledgements: require the current lease token, Spring consumer deduplication: commit the event ID with the mutation.

Continue with checked relay behavior

Continue with Spring outbox claims: lease expiry and token-fenced acknowledgement.

spring
spring-boot
outbox-expiring-lease
Storage details