Skip to content

[2.3] fix: cache strict-validation verdicts by config content#14242

Merged
davidjumani merged 1 commit into
kgateway-dev:v2.3.xfrom
chandler-solo:chandler/14184tier1ajustcaching
Jun 12, 2026
Merged

[2.3] fix: cache strict-validation verdicts by config content#14242
davidjumani merged 1 commit into
kgateway-dev:v2.3.xfrom
chandler-solo:chandler/14184tier1ajustcaching

Conversation

@chandler-solo

@chandler-solo chandler-solo commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Description

Refs #14184.

A fix for the per-client xDS pipeline: the cost amplifier that turns input churn into queue backlog.

Content-hash verdict cache for strict validation

Under KGW_VALIDATION_MODE=STRICT, every translated cluster is validated by forking
envoy --mode validate (~200–500ms per call). Per-client translation runs once per
(backend, client) pair and re-runs on every recompute — all serialized on a single KRT queue
goroutine. At field scale (hundreds of backends, several connected clients) one client
connecting costs thousands of serialized forks; the queue falls minutes behind, and the
snapshot consistency gates — which check per-client rows for presence — evaluate against
mid-drain state and defer publication. The visible symptom is the issue's:
defer building snapshot until all referenced clusters are ready listing clusters that exist
and are healthy. They were queued, not missing. Worse, a gateway pod that crashloops because
its first snapshot never arrives reconnects as a brand-new client and retriggers the full
fan-out — the backlog feeds itself.

A validation verdict is a pure function of the config bytes, so this PR wraps the binary
validator with an LRU cache keyed on the SHA-256 of the marshalled bootstrap:

  • Only deterministic verdicts are memoized (success and ErrInvalidXDS); transient failures
    (exec errors, context cancellation) are never cached. Cached invalid verdicts keep the inner
    error text verbatim and still satisfy errors.Is(err, ErrInvalidXDS).
  • Concurrent misses on identical content collapse to one fork (singleflight).
  • Memory is bounded by entry count (default 4096, KGW_VALIDATOR_CACHE_SIZE); entries are a
    32-byte hash plus a verdict — the config itself is never stored — so steady state is well
    under 1 MB. Eviction is plain LRU.

Cluster config content is identical across clients and recomputes in the overwhelmingly common
case, so the expensive forks collapse even though each (backend, client) pair still translates
independently. KGW_VALIDATOR_MODE selects CACHE (default) or BINARY (the previous
behavior — a one-env-var rollback). Memoization cannot change validation outcomes, only skip
redundant invocations, which is why CACHE is a safe default.

Measured (in-repo benchmarks, 2ms stubbed validation; the real fork costs 100–250x more):

Scenario (200 backends × 8 clients) before after
Connect-event drain (one client joins, full fan-out) 4.03 s 37.5 ms (~107×)
All-unique workload (cache cannot help; overhead bound) 2.273 ms/op 2.274 ms/op (~0%)

Change Type

/kind fix

Changelog

Strict validation (KGW_VALIDATION_MODE=STRICT) now caches validation verdicts by config content
hash, eliminating redundant envoy invocations across per-client translation and recomputes. New
settings: KGW_VALIDATOR_MODE (CACHE [default] | BINARY) and KGW_VALIDATOR_CACHE_SIZE.

Additional Notes

  • The cache lives in pkg/validator behind the existing Validator interface; the translator
    is unchanged apart from the injected implementation.
  • Pairs with the publish-budget PR: this one removes the backlog that makes consistency-gate
    deferrals long; that one bounds the wait when deferrals happen anyway. Either stands alone.
  • Tests: cache hit/miss/eviction, verdict-type discipline, singleflight collapse (one inner
    call under 16 concurrent misses). Benchmarks committed in pkg/validator/validator_bench_test.go
    and pkg/kgateway/proxy_syncer/perclient_bench_test.go.

Copilot AI review requested due to automatic review settings June 12, 2026 16:49
@chandler-solo
chandler-solo requested a review from a team as a code owner June 12, 2026 16:49
@gateway-bot gateway-bot added kind/fix Categorizes issue or PR as related to a bug. release-note labels Jun 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces strict-validation bottlenecks by memoizing envoy --mode validate verdicts based on the bootstrap config content hash, preventing redundant forks across per-client fan-out and recomputes while preserving identical validation outcomes.

Changes:

  • Added an LRU + singleflight–backed caching Validator that caches only deterministic outcomes (success and ErrInvalidXDS) keyed by a SHA-256 content hash.
  • Introduced KGW_VALIDATOR_MODE (CACHE default | BINARY) and KGW_VALIDATOR_CACHE_SIZE settings and wired validator construction through pkg/validator in kgateway setup.
  • Reduced strict RDS validation calls to 1 invocation for valid routes (2 only for invalid routes requiring matcher/action disambiguation), plus added targeted tests/benchmarks.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/validator/validator.go Adds SHA-256 bootstrap hashing helper to support content-based memoization.
pkg/validator/cache.go Implements caching validator with LRU storage and singleflight miss coalescing.
pkg/validator/cache_test.go Adds unit tests for cache hit/miss, eviction, invalid-verdict caching, and singleflight collapse.
pkg/validator/factory.go Adds settings-driven validator constructor (CACHE vs BINARY).
pkg/validator/factory_test.go Tests validator factory wiring and fallback behavior.
pkg/validator/validator_bench_test.go Benchmarks validator mode overhead and cache behavior (stubbed and optional real envoy).
api/settings/settings.go Adds ValidatorMode/ValidatorCacheSize settings and env decoding.
api/settings/settings_test.go Extends settings env var coverage for new validator settings.
pkg/kgateway/setup/setup.go Wires setup default validator creation through the settings-driven factory.
pkg/kgateway/translator/irtranslator/validate.go Optimizes strict route validation to a single full validation on success; disambiguates only on failure.
pkg/kgateway/translator/irtranslator/validate_test.go Tests strict-mode call counts and error attribution (route vs matcher).
pkg/kgateway/translator/irtranslator/backend_validation_test.go Adds integration coverage that strict cluster validation is cached by content and transient errors aren’t cached.
pkg/kgateway/proxy_syncer/perclient_bench_test.go Adds benchmark modeling per-client connect-event drain improvements with caching.
go.mod Promotes github.com/hashicorp/golang-lru/v2 to a direct dependency.
hack/utils/oss_compliance/osa_included.md Records included OSS dependency/license for golang-lru/v2.

Comment thread pkg/validator/factory.go
Comment thread pkg/validator/validator.go
@davidjumani
davidjumani added this pull request to the merge queue Jun 12, 2026
Merged via the queue into kgateway-dev:v2.3.x with commit 96e1330 Jun 12, 2026
35 checks passed
@chandler-solo
chandler-solo deleted the chandler/14184tier1ajustcaching branch June 15, 2026 13:23
@chandler-solo chandler-solo changed the title fix: cache strict-validation verdicts by config content [2.3] fix: cache strict-validation verdicts by config content Jun 15, 2026
chandler-solo added a commit to chandler-solo/kgateway that referenced this pull request Jun 15, 2026
Performance fix; forward port of kgateway-dev#14242

Ref kgateway-dev#14184

Signed-off-by: David L. Chandler <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/fix Categorizes issue or PR as related to a bug. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants