Skip to content

Rate limit ​

Inspect and reset the per-workspace token bucket that the gateway applies to chat completions. The limiter itself is configured via BIGWAVE_RATE_LIMIT_RPS_PER_WORKSPACE and BIGWAVE_RATE_LIMIT_BURST_MULTIPLIER (see the configuration reference); these admin routes operate on the live WorkspaceTokenBucketLimiter attached to app.state at lifespan startup.

The router lives at packages/shared/rate_limit_routes.py.

Endpoints ​

MethodPathAuthSummary
GET/admin/rate-limitBearerInspect the caller's bucket without consuming a token.
POST/admin/rate-limit:resetBearerDrop the caller's bucket; next request gets a full one.

GET /admin/rate-limit ​

Returns the current state of the bucket attached to the calling workspace. This is a read-only probe — it does not consume a token, so dashboards can poll it without skewing the rate.

Response

json
{
  "enabled": true,
  "rps": 10.0,
  "capacity": 20.0,
  "bucket": {
    "allowed": true,
    "limit": 20.0,
    "remaining": 17.5,
    "retry_after_seconds": 0.0,
    "reset_ts": 1715000123.45
  }
}

When the limiter is disabled (env var unset, or rps=0) the response is {"enabled": false} and no further fields are populated. When the limiter is enabled but the workspace has not yet allocated a bucket (no chat traffic since startup), bucket is null.

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  http://localhost:8000/admin/rate-limit

POST /admin/rate-limit:reset ​

Drops the caller's bucket entirely. The next request from the workspace allocates a fresh bucket at full capacity. Useful when testing a deploy under simulated load or after a one-off tenant incident.

Returns 204 No Content on success, 503 when the limiter is not enabled (matching the inspect endpoint's {"enabled": false} shape).

bash
curl -X POST -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  http://localhost:8000/admin/rate-limit:reset

Operator notes ​

  • Workspace fence. The bucket is keyed by the principal's workspace; :reset only drops your bucket, never another tenant's. There is intentionally no admin path for resetting an arbitrary workspace from the bearer surface — flush via process restart if you need that.
  • Disabled vs unwired. 503 from :reset always means rps=0 (or env var unset). A genuinely missing limiter object (lifespan never wired one) collapses into the same path.
  • Headers. When the limiter denies a chat request, the gateway returns 429 Too Many Requests with Retry-After, X-RateLimit-Limit, and X-RateLimit-Remaining headers — the same shape this endpoint reports here.
  • Schema source. RateLimitResult lives at packages/shared/rate_limit.py; the wire shape is built by _to_jsonable at packages/shared/rate_limit_routes.py:20 (so inf capacities are stringified rather than serialised as JSON Infinity).

Dual-licensed: MIT OR Apache-2.0