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.
Circuit breakers¶
Circuit breakers temporarily stop calls to a failing upstream. In LunarGate
0.4.0, their settings are fixed in the gateway implementation. There is no
circuit_breaker YAML section, and failure_threshold or recovery_timeout
cannot be configured. The retry settings above do not change these values.
| Setting | Fixed value | Behavior |
|---|---|---|
| Failure threshold | 5 consecutive failures | Opens the circuit after five failed target executions |
| Recovery timeout | 30 seconds | After this interval, the next call can enter the half-open state |
| Half-open request limit | 3 | Allows up to three trial executions; three consecutive successes close the circuit, while a failure opens it again |
| Closed-state counter interval | 60 seconds | Resets the counters periodically while the circuit is closed |
A target execution wraps its retry sequence. Three failed attempts within one execution count as one circuit-breaker failure, not three. An open circuit rejects execution before contacting that upstream; an eligible request can then proceed to its configured fallback. Recovery is driven by incoming requests, not by a background health probe.
Network failures and upstream HTTP 5xx failures count toward opening the circuit. Client/request errors, client cancellation, client deadlines, and HTTP 4xx responses (including exhausted 429 retries) do not count as provider failures. These outcomes are treated as successful for breaker accounting, so they can reset the consecutive-failure count even when the caller receives an error.
Circuit state is isolated by the effective provider identity, including its
account credentials and endpoint. State changes are logged as
circuit breaker state change with the provider and the old/new states.
For configurable resilience today, use the retry example, provider timeouts, and routing fallback. Exposing breaker thresholds in YAML is planned for 0.4.1; it is not available in 0.4.0.