Skip to content

feat: add redis_decay backend and soft-breach response header - #1214

Closed
ysolomon-plat wants to merge 1 commit into
envoyproxy:mainfrom
depoplabs:pla-8128-redis-decay-backend
Closed

feat: add redis_decay backend and soft-breach response header#1214
ysolomon-plat wants to merge 1 commit into
envoyproxy:mainfrom
depoplabs:pla-8128-redis-decay-backend

Conversation

@ysolomon-plat

Copy link
Copy Markdown

Adds BACKEND_TYPE=redis_decay: a continuously-decaying counter (GCRA family) executed as an atomic Redis EVAL. Unlike the fixed-window redis backend, cache keys carry no window timestamp, so budgets never reset at a boundary and the 2x boundary-burst is impossible by construction. Honors per-descriptor hits_addend. Fail-open on Redis errors. Cluster-safe: EVAL routes by cache key.

Also adds SOFT_BREACH_HEADER_RATIO: when set (0..1), admitted requests whose remaining budget falls inside the soft band get an x-ratelimit-soft-breach: 1 response header, so clients can degrade before hard 429s. Computed generically from CurrentLimit/LimitRemaining, so it works with any cache backend.

Covered by test/redis_decay (real EVAL execution on miniredis: boundary immunity, decay recovery, flood behavior, corrupt data, backward clock, fail-open, hits_addend) and test/service/soft_breach_test.go. All existing tests pass.

Load-tested on Istio 1.30 / Gateway API: 3,950 rps sustained on one replica, +2.3ms p50 overhead, exact admission under concurrency.

Refs #32 (rolling window request, open since 2018).

Adds BACKEND_TYPE=redis_decay: a continuously-decaying counter
(GCRA family) executed as an atomic Redis EVAL. Unlike the fixed-window
redis backend, cache keys carry no window timestamp, so budgets never
reset at a boundary and the 2x boundary-burst is impossible by
construction. Honors per-descriptor hits_addend. Fail-open on Redis
errors. Cluster-safe: EVAL routes by cache key.

Also adds SOFT_BREACH_HEADER_RATIO: when set (0..1), admitted requests
whose remaining budget falls inside the soft band get an
x-ratelimit-soft-breach: 1 response header, so clients can degrade
before hard 429s. Computed generically from CurrentLimit/LimitRemaining,
so it works with any cache backend.

Covered by test/redis_decay (real EVAL execution on miniredis: boundary
immunity, decay recovery, flood behavior, corrupt data, backward clock,
fail-open, hits_addend) and test/service/soft_breach_test.go. All
existing tests pass.

Load-tested on Istio 1.30 / Gateway API: 3,950 rps sustained on one
replica, +2.3ms p50 overhead, exact admission under concurrency.

Refs envoyproxy#32 (rolling window request, open since 2018).
@ysolomon-plat

Copy link
Copy Markdown
Author

Superseded by #1215 (same change, rebuilt with DCO sign-off and cleaned-up comments).

@ysolomon-plat
ysolomon-plat deleted the pla-8128-redis-decay-backend branch August 18, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant