| name | apex-callout-retry-and-resilience |
| description | Strategy layer for resilient Apex HTTP callouts: bounded retry with backoff, queueable async retry chains, circuit-breaker via Platform Cache, idempotency keys, dead-letter pattern. NOT for callout authentication — see apex-named-credentials-patterns. NOT for transaction-boundary rules — see callout-and-dml-transaction-boundaries. NOT a re-write of the HttpClient template — this is the policy and orchestration layer that calls it. |
| category | apex |
| salesforce-version | Spring '25+ |
| well-architected-pillars | ["Reliability","Operational Excellence"] |
| tags | ["apex","callout","retry","circuit-breaker","resilience","idempotency","dead-letter-queue"] |
| triggers | ["how to retry failed http callout in apex","exponential backoff for salesforce apex callout","circuit breaker pattern apex http endpoint","idempotency key on retried payment callout","dead letter queue for failed apex http calls","queueable chain for async retry of webhook"] |
| inputs | ["Target endpoint and method (GET/POST/PUT/DELETE)","Idempotency expectation (safe to retry vs not)","Failure modes observed (timeout, 5xx, 429, network)","Latency budget (sync vs async tolerable)","Volume (per-day callout count and 100-per-tx ceiling)"] |
| outputs | ["Retry policy (attempts, backoff schedule, jitter)","Circuit-breaker configuration (threshold, cooldown, partition key)","Idempotency-Key strategy (header or dedup table)","Dead-letter sObject schema and reprocessing job","MockHttpResponseGenerator test sequence"] |
| dependencies | [] |
| version | 1.0.0 |
| author | Pranav Nagrecha |
| updated | 2026-04-28T00:00:00.000Z |
Apex Callout Retry and Resilience
Activate when an Apex integration must survive transient failures from a downstream system: 5xx errors, network timeouts, 429 rate limits, brief endpoint outages. This skill is the strategy layer — it tells you when to retry, how many times, on what schedule, when to stop, and where to park failures. The HTTP plumbing itself lives in templates/apex/HttpClient.cls.
Before Starting
- Confirm the operation is idempotent (safe to repeat) before retrying writes. If not, an Idempotency-Key contract with the downstream is mandatory.
- Decide sync vs async up front. Synchronous retries fight a 120-second cumulative cap; async retries (Queueable / Platform Event) get a fresh transaction per attempt.
- Identify what's retry-eligible vs not. 5xx, network timeouts, 408, 429, 503 retry. 400, 401, 403, 404, 422 do NOT retry; these are caller bugs or auth failures.
Core Concepts
Retry classification
| Status / Failure | Retry? | Why |
|---|
| Network timeout, no response | Yes | Transient |
| 408 Request Timeout | Yes | Transient |
| 429 Too Many Requests | Yes (honor Retry-After) | Rate limit |
| 500, 502, 503, 504 | Yes | Server-side transient |
| 400, 422 | No | Caller payload bug |
| 401, 403 | No | Auth / authz; refresh token elsewhere |
| 404 | No | Resource doesn't exist |
The Apex synchronous constraint
A synchronous Apex transaction has a 120-second cumulative callout cap and no usable Thread.sleep (Apex offers no sleep primitive — busy-wait loops via System.now() polling are governor-killers and forbidden). This forces synchronous retries to be:
- Bounded — typical 3 attempts max.
- Short-backoff — 100ms / 500ms / 2000ms via the only legal "delay": staying inside the same callout's longer timeout, OR doing minimal CPU work between attempts.
- Aware of the 100-callout-per-transaction limit — every retry counts against it.