@@ -411,17 +411,24 @@ func (r *gubernatorRateLimiter) getDynamicLimit(ctx context.Context,
411411 // Only record the incoming hits when the current rate is within the allowed
412412 // range, otherwise, do not record the hits and return the calculated rate.
413413 // MaxAllowed sets a ceiling on the rate with the window duration. If the
414- // previous period had hits and the window multiplier is suggesting lowering
415- // the ingestion rate then the MaxAllowed will be allowed to go below the
416- // static rate (to as low as `1`). As soon as the window multiplier suggests
417- // increasing the ingestion rate, the MaxAllowed will jump to a minimum of
418- // static rate.
414+ // the window multiplier is suggesting lowering the ingestion rate then the
415+ // MaxAllowed will be allowed to go below the static rate (to as low as `1`).
416+ // As soon as the window multiplier suggests increasing the ingestion rate,
417+ // the MaxAllowed will jump to a minimum of static rate.
419418 //
420419 // NOTE(marclop) We may want to add a follow-up static ceiling to avoid
421420 // unbounded growth.
422421 var maxAllowed float64
423- if previous > 0 && windowMultiplier <= 1 {
424- maxAllowed = max (1 , previous * windowMultiplier )
422+ if windowMultiplier <= 1 {
423+ // multiplier indicates scale down. If we have hits in the previous
424+ // multiplier then scale that down, otherwise scale the static rate
425+ // as per the multiplier instead of returning the default static rate.
426+ // This should protect against deployments with spiky load patterns.
427+ if previous > 0 {
428+ maxAllowed = max (1 , previous * windowMultiplier )
429+ } else {
430+ maxAllowed = max (1 , staticRate * windowMultiplier )
431+ }
425432 } else {
426433 maxAllowed = max (staticRate , previous * windowMultiplier )
427434 }
0 commit comments