Definition · Goodput, and the overload modelGoodput is the rate of requests that are both served and still wanted. With capacity C and offered load L, this lesson's model is: for L ≤ C the goodput is L; for L > C the server's capacity is spread across L requests, only C/L of them complete within the client's patience, and the goodput is C × (C/L). A shedder with threshold T admits min(L, T) and passes it through the same model.
The model is this lesson's own and it is stated so that it can be argued with. The mechanism behind it — a queue that fills, work spent on entries whose clients have already left, and an admitted rate that is not the completed rate — is the subject of Queues and Utilisation's “Bounded Queues and Loss”, and the knee that makes the threshold choice non-obvious is “The Knee: Response Time vs Utilisation”.
C = 1000 rps, threshold T = 900 rps
offered load goodput shedding goodput not shedding ratio
50% 500 500.0 500.0 1.00
90% 900 900.0 900.0 1.00
100% 1000 900.0 1000.0 0.90
150% 1500 900.0 666.7 1.35
200% 2000 900.0 500.0 1.80
300% 3000 900.0 333.3 2.70
400% 4000 900.0 250.0 3.60
Two features of the table decide everything. The shedder costs goodput at exactly one point — between the threshold and capacity, where it is refusing work the server could have done — and that cost is bounded by C − T, here a hundred requests a second. Everywhere above capacity it wins, and the margin grows without limit as the load rises.
Where to put the threshold
The cost of a threshold below capacity is C − T at full load; the benefit is that the system never enters the collapsing regime. Since response time is already rising steeply as utilisation approaches one, the threshold is normally placed a little under capacity — 0.9C here — and the ten per cent is bought as insurance against the estimate of C being wrong.
Example · A threshold above capacity still collapsesSet the threshold to 120% of capacity and offer 200%. The shedder admits 1200 requests a second, which the server cannot serve, so the goodput is 1000²/1200 = 833.3 a second — better than the 500 of no shedding and worse than the 900 of a threshold at 90%. The shedder is not a magic boundary; it is a cap, and a cap above capacity caps nothing that matters.
Utilisation is the quantity being defended
With the shedder the utilisation is admitted/C = 0.9; without it, offered/C = 2.0. A utilisation above one is not a state a system occupies, it is a description of a queue growing without bound, and every second spent there adds latency that never comes back. The shedder's real product is that 0.9.
Example · The circuit breaker, from the other endA circuit breaker is the same arithmetic with the client doing the refusing. After a threshold number of failures the client stops calling for a cooling period and fails fast locally, which removes its share of L at the source rather than at the server's door. The advantage over server-side shedding is that the rejected request never crosses the network; the disadvantage is that the client is deciding on stale local evidence about a service it has stopped observing.
Both mechanisms are about the same quantity and neither of them makes the offered load smaller. The requests that are shed still failed from the user's point of view — the argument is not that rejection is free, it is that rejection is cheap and collapse is not, so a fixed amount of failure buys far more successes when it is taken at the door.
Example · Why this is not a loss of availabilityAt 200% offered load the unshed service succeeds on 500 of 2000 requests a second, a success ratio of 25%. The shed service succeeds on 900 of 2000, a ratio of 45%, while explicitly rejecting 1100. By the error-budget measurement of “Error Budgets”, which counts failed requests, the shedder spends less budget — 1100 rejections against 1500 timeouts a second — and the rejections are returned immediately rather than after a timeout.