PPactDocs
Administration

Rate limits

Per-tenant, per-endpoint request throttling — glob-matched policies with block, throttle, or log-only enforcement and an incident log.

Rate limits

Rate limits let you cap request volume per endpoint for your tenant. Policies are sliding-window counters matched by URL glob, with a choice of enforcement, and every breach is recorded so you can see who hit a limit and when.

The control lives at Admin → Rate limits and is backed by core.tenant_rate_limit, applied in the request path by api/rate_limit_middleware.py.

Real middleware enforcement

Policies are read on the request path through a 60-second in-process TTL cache and counted in Redis (or an in-process backend in dev) for cross-replica consistency. Matching requests are counted and enforced before the handler runs.

How policies match

Each policy has an endpoint_pattern glob. The most specific match wins:

code
/v1/email/send   → exact match      (highest specificity)
/v1/email/*      → prefix glob
*                → global catch-all  (default policy)

When several policies match, the longest-prefix / exact match takes precedence; ties break toward the lowest policy id.

Enforcement modes

Each policy sets one of:

  • block — reject requests over the limit (HTTP 429).
  • throttle — slow rather than hard-reject.
  • log_only — count and record, but never reject. Use this to size a limit against real traffic before turning on enforcement.

Fail-open by design

Rate limiting never blocks legitimate traffic on error

Every public function in the enforcement path catches exceptions and returns a permissive result rather than crashing the request. A misconfigured Redis or a stale cache degrades to "allow", not "500". auth.rate_limit.exceeded audit events are also sampled — at most one per 100 occurrences per (tenant, policy) — so a sustained attack can't flood the audit table.

API

Admin/owner only (Permission.ADMIN_FLAGS), tenant-scoped from the auth context — you can never read or write another tenant's policies:

code
GET    /v1/rate-limits/policies              # list this tenant's policies
POST   /v1/rate-limits/policies              # create a policy
PATCH  /v1/rate-limits/policies/{id}         # update a policy
DELETE /v1/rate-limits/policies/{id}         # delete a policy
POST   /v1/rate-limits/policies/seed-defaults# seed a sensible default set
GET    /v1/rate-limits/incidents             # recent rate-limit-exceeded events
GET    /v1/rate-limits/analytics             # aggregated breach analytics
GET    /v1/rate-limits/usage                 # current usage vs. limits
GET    /v1/rate-limits/usage/banner          # per-user near-limit banner signal

A policy takes requests_per_window (1…100,000), window_seconds (1…86,400, default 60), endpoint_pattern (default *), enforcement, and enabled. Policies are stored in tenant_rate_limit_policies (alembic 0104_tenant_rate_limit_policies).

Distinct from AI call-rate limits

These are HTTP-endpoint limits. The per-minute call-rate limits on AI features are a separate, in-memory gate configured on the AI budget page — don't confuse the two.