Per-principal token-bucket rate limiting at HTTP ingress #3

Open
opened 2026-05-06 05:45:12 +00:00 by anuna-02 · 0 comments
anuna-02 commented 2026-05-06 05:45:12 +00:00 (Migrated from codeberg.org)

Context

The router's ingress today protects against capacity overflow with a per-capability FIFO bounded at 1000 pending. Producers receive 429 + Retry-After when the FIFO is full, and retries are deduplicated by Idempotency-Key.

What's missing: per-principal limits. All asks from one authenticated principal share the per-capability FIFO with all other principals targeting the same capability. A single noisy or misbehaving producer can monopolise a FIFO and deny service to other legitimate principals.

Acceptable for the v0.1 deployment with a small number of trusted producers; not safe to expand to multi-tenant hosting or open producer onboarding without per-principal flow control.

Proposed change

Add a per-principal token bucket at the ingress layer, evaluated before the per-capability FIFO check.

  • Configurable per-principal burst and steady_rate (asks/sec).
  • Permissive default matching current legitimate traffic (suggest burst = 50, steady = 10/s).
  • Per-principal overrides via auth policy (mapping sub claim → bucket parameters).
  • On bucket-empty, return 429 + Retry-After with the same shape as the FIFO-full response.

Implementation: a gen_server per principal, garbage-collected after a configurable idle window.

Acceptance

  • Config: [ingress.rate_limit] default_burst = N, default_steady = M, idle_gc_seconds = K.
  • Per-principal overrides via authz policy hook (interface, not full implementation, in this issue).
  • Tests:
    • Principal within bucket → 202.
    • Principal exceeds bucket → 429 + Retry-After.
    • Two principals on the same capability cannot starve each other.
    • Bucket replenishes at the steady rate.
  • Observability: per-principal rejected_count and current_tokens exposed at /metrics.

Refs

  • SPEC-001 NFR-class on backpressure
  • PROTO-002 (Nondeterministic Idempotence) — particularly RULE-NDI-005 on multiple observers / fairness
  • cbcl-runtime deck slide 17 (Flow control)
## Context The router's ingress today protects against capacity overflow with a per-capability FIFO bounded at 1000 pending. Producers receive `429 + Retry-After` when the FIFO is full, and retries are deduplicated by `Idempotency-Key`. What's missing: per-principal limits. All asks from one authenticated principal share the per-capability FIFO with all other principals targeting the same capability. A single noisy or misbehaving producer can monopolise a FIFO and deny service to other legitimate principals. Acceptable for the v0.1 deployment with a small number of trusted producers; not safe to expand to multi-tenant hosting or open producer onboarding without per-principal flow control. ## Proposed change Add a per-principal token bucket at the ingress layer, evaluated **before** the per-capability FIFO check. - Configurable per-principal `burst` and `steady_rate` (asks/sec). - Permissive default matching current legitimate traffic (suggest `burst = 50, steady = 10/s`). - Per-principal overrides via auth policy (mapping `sub` claim → bucket parameters). - On bucket-empty, return `429 + Retry-After` with the same shape as the FIFO-full response. Implementation: a `gen_server` per principal, garbage-collected after a configurable idle window. ## Acceptance - [ ] Config: `[ingress.rate_limit] default_burst = N, default_steady = M, idle_gc_seconds = K`. - [ ] Per-principal overrides via authz policy hook (interface, not full implementation, in this issue). - [ ] Tests: - Principal within bucket → 202. - Principal exceeds bucket → 429 + Retry-After. - Two principals on the same capability cannot starve each other. - Bucket replenishes at the steady rate. - [ ] Observability: per-principal `rejected_count` and `current_tokens` exposed at `/metrics`. ## Refs - SPEC-001 NFR-class on backpressure - PROTO-002 (Nondeterministic Idempotence) — particularly RULE-NDI-005 on multiple observers / fairness - `cbcl-runtime` deck slide 17 (Flow control)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
anuna-research/cbcl-router#3
No description provided.