Skip to content

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: true when 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 by max_delay.
  • Keep the per-attempt provider timeout in mind: max_attempts is capped at 10 so one request cannot create an unbounded chain of timeouts or upstream load.
  • Extreme computed delays saturate at max_delay instead 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>.timeout limits one upstream attempt
  • providers.<id>.timeout_mode: ttft means the provider only needs to produce the first response byte before the timeout expires
  • providers.<id>.timeout_mode: total means the full response must finish before the timeout expires
  • retry.max_attempts then 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.