HTTP retry policy
Stormedo retries temporary delivery failures using bounded exponential backoff. Each completed attempt includes the retry decision and the next retry time when another attempt is scheduled.
Retryable outcomes
Section titled “Retryable outcomes”These outcomes are retryable while attempts remain:
- DNS failures
- Connection failures
- Per-attempt timeouts
- HTTP
408 Request Timeout - HTTP
429 Too Many Requests - HTTP
5xxresponses
Normal HTTP 4xx responses are not retried by default because they usually require a change to the request or destination.
Defaults by submission path
Section titled “Defaults by submission path”| Submission | Default total attempts | Setting |
|---|---|---|
Quick send POST /send |
1 | retry counts additional attempts. |
Advanced POST /requests and batch items |
3 | retry.max_attempts counts total attempts. |
| SDK JSON send and batch | 3 | maxAttempts / max_attempts counts total attempts. |
| SDK raw-body send | 1 | maxAttempts / max_attempts counts total attempts. |
| Recurring schedule occurrence | 1 | HTTP request.retry counts additional attempts; SDK maxAttempts / max_attempts counts total attempts. |
A configured total-attempt budget is between 1 and 20. Set it explicitly when consistent behavior across endpoints matters. At-least-once execution still requires duplicate-safe receivers.
Quick-send attempt limits
Section titled “Quick-send attempt limits”The retry query parameter on POST /send counts retries after the initial attempt.
POST /send?url=https://your-app.example/webhook&retry=3This configuration permits four total attempts: one initial attempt and up to three retries.
retry accepts values from 0 through 19.
Advanced attempt limits
Section titled “Advanced attempt limits”The advanced POST /requests API and SDK maxAttempts or max_attempts options count total attempts, including the initial call.
{ "url": "https://your-app.example/webhook", "retry": { "max_attempts": 4, "backoff": "exponential" }}This configuration also permits four total attempts.
Backoff timing
Section titled “Backoff timing”After consecutive retryable failures, the waits are 1s, 5s, 25s, 125s, then 300s for each remaining retry. There is no jitter. Each wait begins after the failed attempt completes; execution can start later than the planned time.
All 2xx responses succeed. Redirects (3xx) are not followed and are terminal failures. Stormedo does not inspect the response body for application-level success or failure.
Retry-After
Section titled “Retry-After”For retryable responses, Stormedo respects a valid Retry-After header when it requests a longer wait than the normal backoff.
The header can contain a non-negative integer number of seconds or an HTTP date. Stormedo selects the greater of backoff and the parsed delay, capped at 24 hours. Past dates produce a zero requested wait, so normal backoff still applies. Invalid or truncated values do not replace backoff.
Completed attempt history records both delays, the selected delay, the source, and next_attempt_at. A retryable response with no attempts remaining is final; it does not create another wait.
Per-attempt timeout
Section titled “Per-attempt timeout”The default timeout is 50s. Quick send accepts a whole-second or whole-minute timeout from 1s through 5m.
POST /send?url=https://your-app.example/webhook&timeout=45sThe timeout applies to each delivery attempt, not the complete request lifecycle.
Final failure
Section titled “Final failure”A request becomes failed when an outcome is not retryable or when no configured attempt remains. Completed attempts remain available through request detail and the dedicated attempt-history endpoint.