Retryable Error Classification
resilience
Definition
Partition every failure a request can produce into retryable (presumed transient — infrastructure and network faults; a later identical attempt may succeed) and non-retryable (deterministic — validation and state errors; every identical attempt will fail the same way), and make the classification part of the response contract so clients and frameworks know mechanically whether re-attempting under the same idempotency key is permitted. Default conservatively: for operations with irreversible side effects, an unclassified error is non-retryable.
The classification converts 'retries are safe' from a global assumption into a per-error contract, and both mislabel directions carry a named price: transient-marked-permanent fails the request forever, with every retry parroting the wrong verdict; permanent-marked-transient re-opens the door to duplicated side effects and manual cleanup. Boundary against Retry Budget: the budget governs how much retrying a system can afford; classification governs whether a given failure may be retried at all.
When it applies
- Idempotent request frameworks where retry decisions must be automatic rather than per-call-site judgment
- APIs whose errors mix infrastructure faults (5XX-shaped) with validation and state errors (4XX-shaped)
- Operations with irreversible side effects, where a wrong 'retryable' verdict costs more than a wrong 'permanent' one
Tradeoffs
- Every exception path needs a deliberate label, maintained as the codebase grows — the contract is only as good as its worst-classified error
- Ambiguous cases (a null from a connectivity blip vs a null from bad input) require context the classification layer may not have
- A conservative default protects side effects by silently converting some transient faults into permanent failures needing human unsticking
Seen in
- Airbnb EngineeringApr 16, 2019
At Most Once: Orpheus and the Idempotent Payments Library at Airbnb
Partition all failures into retryable (presumed transient; safe under the same key) and non-retryable (deterministic; replay the recorded failure), with a conservative default. The classification converts 'a retry is safe' from a global property into a per-error contract.