{"record":{"id":"237d6f4b2995d4d6","repo":"vitessio/vitess","slug":"ignoring-lower-bad-rate-of-v-because-such-a-high","errorCode":null,"errorMessage":"ignoring lower bad rate of %v because such a high degradation (%.1f%%) is unlikely (current highest good: %v)","messagePattern":"ignoring lower bad rate of (.+?) because such a high degradation \\(%\\.1f%%\\) is unlikely \\(current highest good: (.+?)\\)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"go/vt/throttler/memory.go","lineNumber":119,"sourceCode":"func (m *memory) markBad(rate int64, now time.Time) error {\n\t// Bad rates are rounded up instead of down to not be too extreme on the\n\t// reduction and account for some margin of error.\n\trate = m.roundUp(rate)\n\n\t// Ignore higher bad rates than the current one.\n\tif m.bad != 0 && rate >= m.bad {\n\t\treturn nil\n\t}\n\n\t// Ignore bad rates which are too drastic. This prevents that temporary\n\t// hiccups e.g. during a reparent, are stored in the memory.\n\t// TODO(mberlin): Remove this once we let bad values expire over time.\n\thighestGood := m.highestGood()\n\tif rate < highestGood {\n\t\tdecrease := float64(highestGood) - float64(rate)\n\t\tdegradation := decrease / float64(highestGood)\n\t\tif degradation > 0.1 {\n\t\t\treturn fmt.Errorf(\"ignoring lower bad rate of %v because such a high degradation (%.1f%%) is unlikely (current highest good: %v)\", rate, degradation*100, highestGood)\n\t\t}\n\t}\n\n\t// Delete all good values which turned bad.\n\tgoodLength := len(m.good)\n\tfor i := goodLength - 1; i >= 0; i-- {\n\t\tgoodRate := m.good[i]\n\t\tif goodRate >= rate {\n\t\t\tgoodLength = i\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\tm.good = m.good[:goodLength]\n\n\tm.bad = rate\n\tm.touchBadRateAge(now)\n\treturn nil","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/throttler/memory.go#L101-L137","documentation":"memory.markBad() ignores a 'bad' rate that is more than 10% below the current highest good rate, because such a drastic drop is statistically unlikely to indicate a real capacity change (more likely noise). The bad observation is discarded and this error is returned.","triggerScenarios":"markCurrentRateAsBadOrGood calls markBad(rate) when rate < highestGood and (highestGood-rate)/highestGood > 0.1, e.g. a transient measurement dip after the throttler is told the current rate was bad.","commonSituations":"A single slow query or temporary stall causes a spiky low observed rate; throttler threads report rates unevenly under low concurrency.","solutions":["No action needed — the module deliberately ignores implausible drops.","If degradation is real, it will be observed repeatedly; sustained bad rates below the 10% threshold will eventually be recorded.","Check for measurement artifacts (low thread count, short sampling window) if valid degradations are being ignored."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := mem.markBad(rate); err != nil {\n    log.Debug(\"bad rate ignored as implausible\", slog.Any(\"error\", err))\n}","preventionTips":["Treat as expected filtering of outliers; no operator action.","Ensure enough throttler threads report rates so dips aren't spiky.","If real degradations are ignored, check sampling window and thread count settings."],"tags":["go","throttler","rate-limiting"],"backgroundTag":"throttler-rate-rejected","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}