Skip to main content

Overview

KavachOS applies rate limits at two layers: auth endpoints get IP-based limits to protect against brute force and credential stuffing, and the permission engine enforces per-agent call limits via the maxCallsPerHour constraint. Both layers return a standard 429 response and set Retry-After when applicable.

Built-in auth endpoint limits

These limits apply automatically with no configuration required.
Limits are tracked in-process by default. For multi-instance deployments, configure a Redis store so all instances share the same counters.

Configuring auth limits

Pass a rateLimit block to createKavach to override the defaults or enable Redis:
"memory" | "redis"
default:"\"memory\""
Where to persist counters. Use redis in production when running multiple instances.
string | undefined
Redis connection string. Required when store is redis.
{ limit: number; window: number }
Override for the sign-in endpoint. window is in seconds.
{ limit: number; window: number }
Override for the sign-up endpoint.

Per-agent limits with maxCallsPerHour

The permission engine supports a maxCallsPerHour constraint. When an agent exceeds its hourly call budget, the permission check returns allowed: false with reason: "Rate limit exceeded".
The counter resets at the top of each clock hour. If you need sliding windows, use createRateLimiter instead (see below).

Checking the limit in your code

createRateLimiter

Use createRateLimiter for custom rate limiting on your own endpoints, for example, an expensive AI inference route that should be capped per user.
number
Maximum number of requests allowed within the window.
number
Time window in seconds.
(req: Request) => string
Derives the rate limit key from the request. Defaults to the client IP.
"memory" | "redis"
default:"\"memory\""
Counter storage backend.
string | undefined
Redis connection string. Required when store is redis.

withRateLimit middleware

Wrap any handler with withRateLimit to apply a limiter without modifying the handler itself.
When the limit is exceeded, withRateLimit returns a 429 response automatically and does not call the wrapped handler.

429 response format

All rate limit rejections, from auth endpoints, the permission engine, or withRateLimit, return the same shape:
The Retry-After header is also set to the number of seconds remaining in the current window.

Next steps

Permissions

Add maxCallsPerHour and other constraints to individual permissions.

Approval flows

Pair rate limits with human-in-the-loop approval for sensitive actions.

Anomaly detection

Use anomaly scoring alongside rate limits for behavioural signals.
Last modified on April 29, 2026