retry¶
The retry section controls upstream retry behavior.
Fields¶
| Field | Type | Default | Notes |
|---|---|---|---|
enabled |
bool | true |
master switch |
max_attempts |
integer | 3 |
total attempts including the first request; must be between 1 and 10 |
initial_delay |
duration | 1s |
first backoff delay |
max_delay |
duration | 30s |
upper cap for backoff |
multiplier |
float | 2.0 |
exponential backoff multiplier |
jitter_factor |
float | 0.2 |
random jitter added to backoff |
retryable_errors |
list[int] | [429, 500, 502, 503, 504] |
HTTP statuses treated as retryable |
When retrying is enabled, delays must be non-negative, max_delay must be at least initial_delay, multiplier must be a finite value of at least 1, and jitter_factor must be between 0 and 1. Invalid values are rejected during startup or hot reload.
Example¶
retry:
enabled: true
max_attempts: 3
initial_delay: 500ms
max_delay: 10s
multiplier: 2.0
jitter_factor: 0.1
retryable_errors: [429, 500, 502, 503, 504]
Practical guidance¶
- Keep retries enabled for hosted providers unless your app already handles retries upstream.
- Pair retry with routing fallback so transient failures can move traffic to another target when needed.
- Use request header
X-LunarGate-No-Retry: truewhen a caller needs a single-shot request. - For retryable responses, LunarGate honors both delta-seconds and HTTP-date forms of
Retry-After. The wait is the greater of the configured exponential backoff and the provider's requested delay, capped bymax_delay. - Keep the per-attempt provider timeout in mind:
max_attemptsis capped at10so one request cannot create an unbounded chain of timeouts or upstream load. - Extreme computed delays saturate at
max_delayinstead of overflowing the runtime duration range.
Important nuance¶
Client disconnects and timeouts are treated separately from provider failures. They should not be treated as normal retry/fallback failures in the gateway.
Provider-level timeout is configured under providers, not under retry.
providers.<id>.timeoutlimits one upstream attemptproviders.<id>.timeout_mode: ttftmeans the provider only needs to produce the first response byte before the timeout expiresproviders.<id>.timeout_mode: totalmeans the full response must finish before the timeout expiresretry.max_attemptsthen decides whether the gateway should try again after that timed-out attempt
Observability reports retry_count as the number of attempts after each target's initial call. When a fallback target is used, the value is accumulated across the primary and fallback targets; moving to a fallback is not itself counted as a retry.