Shed requests above a configured admission rate #121
No reviewers
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-proxy!121
Loading…
Reference in a new issue
No description provided.
Delete branch "configurable-rate-limits"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #110: configurable rate limit, default 1 per second, anything above it shed with 429.
Design
A token bucket per logical route, so a busy route cannot starve a quiet one.
PROXY_RATE_LIMIT_PER_SECOND- sustained rate. Default1.0.0disables shedding.PROXY_RATE_LIMIT_BURST- bucket capacity. Default1.The check sits after route resolution and before admission:
/healthz,/readyz,/metricsare never shedResponse carries
Retry-Afterin whole seconds, minimum 1. The recorded error code israte_limited, kept apart fromrate_limit_errorso the queue-full path and the rate path stay separable. Counter:llm_rate_limited_total{logical_model}.The one decision worth your eye
burst=1means two requests in the same second sheds the second.That is the literal reading of "1 per second" and the right sustained number against measured traffic of 0.0047 req/s. It is also the setting most likely to be wrong for a tool-using turn, which issues its model rounds back to back rather than spread over seconds - the turn in #113 ran six rounds inside 97 seconds, several following one another immediately. Under this default, that turn sheds.
I shipped the default you asked for rather than quietly picking a safer one. If
sirens-echoshould keep working unchanged, Deploy wantsPROXY_RATE_LIMIT_BURSTat or above the number of rounds a turn can issue, with the per-second rate left alone: the rate bounds sustained load, the burst decides whether one legitimate turn survives.docs/rate-limits.mdsays this where an operator will find it.How to verify
ward exec test-tests/test_ratelimit.py, 12 cases.test_first_request_passes_and_the_next_shedsis the shipped default end to end.test_an_unknown_model_still_404s_rather_than_spending_a_tokenpins the ordering.test_health_routes_are_never_shedpins the exemption.Retry-Afterare tested on a controlled clock, so no test sleeps.Test plan
ward exec format-check,lint,typecheck,pre-commitall cleanRisk
High until the burst is set for the deployment, entirely because of the default above. The mechanism itself is small and self-contained: one new module, one call site per serving route, no change to the dispatch path.
tests/conftest.pypins the rate off for the rest of the suite, because every other test fires far above 1/s and would otherwise be testing this instead.Note
Branched off
main, independent of the other open PRs.