Metastable Failure Explorer

Retries make a service its own sustaining effect. Enter a service, its dependency and its retry policy; this page solves the amplification fixed point, enumerates every equilibrium, and finds the two control values that bracket the hysteresis loop: the one that tips you in, and the very different one that gets you out.

Solving.

Model

Parallel servers in the M/M/c queue.
Per server. Service rate mu = 1000 / this.
First attempts only. Retries are derived.
An attempt fails when its wait exceeds this.
1 means no retry. Google SRE guidance is 3.
Cap on retries as a share of first attempts.
Service rate is the control that reproduces a tip at moderate utilization.
Low and high end of the control sweep.

Equilibria of the entered model

The dependency sees lambda_eff, the total attempt rate. Each attempt fails with probability p(lambda_eff), the M/M/c chance that a request waits longer than the client timeout. A request that fails is retried, so lambda_eff = lambda * sum over i of p(lambda_eff) to the i. Every root of that equation is an equilibrium. A root is stable when the slope of the right-hand side is below 1 there, which is what makes the collapsed root something the system stays in.

EquilibriumAttempt rateUtilizationTimeout rate pGoodputSlopeState
amplified load F(lambda_eff) identity line equilibrium

Hysteresis: the way in and the way out are different numbers

leg 1: control moved toward failure leg 2: control moved back

Transient engine: what backoff actually changes

Delay does not appear anywhere in the fixed-point equation above, so a backoff control cannot move an equilibrium. It moves timing. This is a separate fluid simulation: retries are scheduled into future time bins by the backoff policy, and the timeout rate is re-evaluated from the instantaneous attempt rate in each bin. Same model, same equilibria, different path through them.

Jitter policyPeak attempt rateMean goodput, last quarterTime at zero goodputOutcome
no jitter equal jitter full jitter dependency capacity

Numerics, checked in the page

Erlang C written the textbook way needs a^c / c!. In float64, 171! is not finite and a^c stops being finite well before that, so the textbook form returns a non-finite value on any fleet worth modelling. This page computes the same quantity in log space, using lgamma for the factorial term, so the ratio stays finite. These four lines are computed by this page, in your browser, from the model above.

CheckLog-space resultIndependent resultRelative difference

What this refuses to compute

Sources

Related