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.

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.