advanced24 min studyLesson 376 in Engineering

Proxy retries: one user operation can create many attempts

Count retries across layers, bound deadline consumption, and separate safe repetition from duplicate side effects.

On this page

What you’ll understand

  • Compute a layered worst-case attempt count using retries after the initial attempt.
  • Distinguish per-attempt timeout, overall deadline, and active retry budget.
  • Explain why a transport failure can leave an application operation's outcome ambiguous.

A retry can rescue a request from a transient failure, but it is additional work at the moment the dependency may already be struggling. Applications, SDKs, gateways, and mesh proxies can each repeat the same operation. Count attempts across the complete path and specify which layer owns retry policy before calling a small local retry count harmless.

Attempts multiply across independent retry layers

One retry means at most two attempts: the original plus one repeat. If a client can make three attempts and each traversed proxy can make two upstream attempts, the downstream can receive as many as six attempts for one original operation. Add another independently retrying layer and the multiplication continues. This is a worst-case upper count assuming every layer reaches its local cap and every attempt reaches the next layer. Eligibility rules, rejections, cancellation, deadlines, and successes can reduce actual work.

Distinguish logical operations, downstream attempts, upstream attempts, and successful completions in telemetry. A proxy receiving one request may start several upstream attempts, while a retried user request can look like a new downstream request unless identifiers preserve the relationship. If the upstream committed an operation and its response was lost, a connection reset does not prove the operation failed. Retrying a write requires application semantics such as an idempotency key and a defined deduplication contract; transport-level retry machinery alone cannot promise exactly-once effects.

Amax⁡=∏j=1d(1+rj)A_{\max}=\prod_{j=1}^{d}(1+r_j)
r_j is a nonnegative integer retry cap after the first attempt at each of d independently repeating layers. A_max counts worst-case final-layer attempts per original operation under full cap exhaustion and no pruning by deadlines, successes, or rejection. It is not expected traffic.↔ Scroll wide equations horizontally.

A retry budget is not just another timeout

A per-attempt timeout bounds waiting for one try, while an overall deadline limits the logical request's total permitted duration across attempts and backoff. Envoy v1.40.0 documents retries within its overall request timeout, with route and header configuration affecting the policy. An application may have an even shorter deadline that needs propagation and cancellation. A retry started with too little remaining time can consume backend work that cannot produce a useful response. Hedging is different again: concurrent attempts can overlap rather than waiting for an earlier attempt to finish.

A retry budget limits how much extra retry work is allowed relative to an explicitly defined population, often active requests in a proxy's cluster rather than a global count of user operations. Envoy's active-retry resources and retry-budget mechanism have documented scopes; do not interpret them as an automatically coordinated fleet percentage. Backoff and jitter reduce synchronization but do not create capacity. Retry only eligible failures, choose whether a different host is useful, and avoid immediate retries of persistent authorization failures or deterministic validation errors.

E[A]=1+p+p2for at most two retries\mathbb{E}[A]=1+p+p^2\quad\text{for at most two retries}
Each attempted call independently fails with the same probability p, and the policy retries every such failure until success or three total attempts. This expectation excludes deadlines, correlated failures, cancellation, and other retry layers. It is not valid during an arbitrary overload incident.↔ Scroll wide equations horizontally.

Budget the whole failure path

During a controlled failure, compare original-operation rate with attempted backend rate and completed useful work. Record the reason for each retry, consumed deadline, retry overflow, cancellation, and duplicate-effect handling. A falling user-visible error rate may be bought with sharply increased backend CPU and worsen other users' latency. Test a full dependency outage and a slow response after commitment, not only a single quick reset. Coordinate policy changes across layers so disabling one proxy retry does not leave a larger hidden SDK amplification untouched.

The queue lab illustrates changed offered work, not retry execution. Reset, set λ=2 and μ=3, predict the initial four-unit backlog drains in four seconds, then Play or Step. Separately Reset, set λ=4 and μ=3, predict growth of one unit per second, then Play or Step. Treat each unit as a backend attempt only for this synthetic comparison. The instrument does not generate retries, preserve operation IDs, implement backoff, or cancel side effects. Explain how more attempts can cross a service-capacity boundary even when original user demand remains unchanged.

Three small policies create eighteen attempts

A client permits two retries, a gateway permits one retry per received attempt, and a source proxy permits two retries per gateway attempt. Suppose all attempts fail quickly and every local cap is exhausted before any deadline.

  1. Convert retries to total attempts: the client allows 3, the gateway 2, and the source proxy 3 for each incoming attempt at that layer.

  2. Multiply: 3×2×3=18 possible backend attempts for one original operation. At 100 original operations/s, the corresponding worst-case offered attempt rate is 1,800/s under these strong assumptions.

  3. For comparison, a separate single-layer model with failure probability 0.2 and two retries has expected attempts 1+0.2+0.04=1.24. Do not substitute this independent steady-probability expectation for the layered all-failure bound.

The result

Local retry counts must be converted to attempts and composed across the actual path. Success, deadlines, and budgets determine how much of the bound is realized.

Explore the model

Interactive lab

Interactive lab · queue

Extra attempts can consume the remaining headroom

Reset, set λ=2 and μ=3, predict four initial attempt units drain in four seconds, then Play or Step. Separately Reset, set λ=4 and μ=3, predict one additional waiting unit per second, then Play or Step. The fluid instrument does not generate retries, backoff, hedges, or idempotency behavior.

Extra attempts can consume the remaining headroomFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forRetry work changes backend demand even when the original user-operation rate is unchanged.

Check your understanding

Why can retrying after a lost response duplicate a write?

Try it yourself

An overall budget is 200 ms. Two sequential attempts each use 80 ms with a 20 ms backoff between them. A proposed third attempt needs another 40 ms backoff and 80 ms execution. Does that schedule fit?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Count both elapsed attempts and all planned backoff against the overall budget.

Compare with the solution

The first two attempts and their backoff total 80+20+80=180 ms. The proposed third adds 40+80=120 ms, totaling 300 ms, so it cannot fit the 200 ms schedule. A remaining 20 ms does not justify launching an operation requiring the assumed 120 ms path; real cancellation also needs backend cooperation.

Take it with you

  • Compose total attempts across every retrying layer.
  • Deadlines, active retry budgets, and backoff control different dimensions.
  • Ambiguous transport outcomes require application-level repetition semantics.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.