A database commit cannot send an email
Why external side effects create a second failure boundary.
The outbox records unfinished work
Save a domain change and its delivery obligation atomically.
A worker claims one available job
Why concurrent workers need a database claim rather than a shared array.
A lease expires when a worker disappears
Recover abandoned jobs and reject completion by an outdated claimant.
Retry a temporary failure with a limit
Separate retryable failures from invalid work and avoid retry storms.
A retry can represent the same operation
Persist an operation key and result so lost responses do not create duplicate work.
One idempotency key has one meaning
Reject changed input instead of returning an unrelated cached response.
SMTP acceptance is not inbox delivery
Understand what the email worker can prove and where duplicates arise.
Exhausted jobs need a recovery decision
Preserve failed work, inspect the cause, and replay without losing ownership rules.
Two systems can disagree temporarily
Use durable intent, stable provider keys, and reconciliation across external boundaries.