Rate Limit Best Practices¶
Olla limits requests per client IP and across all clients. The limits apply to the proxy routes and to the translator routes, /olla/anthropic/v1/messages, /olla/anthropic/v1/messages/count_tokens and /olla/anthropic/v1/models. Status, health and stats endpoints are not limited. The settings are in Rate Limits.
How Claude Code behaves¶
Measured against Olla with a real Ollama backend (Claude Code 2.1.302, headless, all sessions from one IP, limits open):
| Case | Requests | Peak per 1s | Peak per 10s | Peak per 60s |
|---|---|---|---|---|
| One session, a normal coding task | 2 to 3 | 1 | 1 | 2 |
| Three parallel sessions (stand-ins for parallel subagents) | 11 | 3 | 3 | 9 |
| Four parallel sessions starting together | 5 | 4 | 4 | 5 |
- Claude Code sent only
POST /olla/anthropic/v1/messages. Each model turn, including a retry, is one request. The headless runs made nocount_tokensormodelscalls; allow a few per interactive session. - Parallel sessions start together, so the burst matters more than the sustained rate: four requests arrived in the first second of the four-session run.
- Each turn carries a large prompt, so on local hardware a session issues a request every 10 to 30 seconds. A fast backend answers sooner and a session loops faster. Treat these numbers as a floor, and expect a single session on fast hardware to approach 30 requests a minute.
The defaults (100 per IP per minute, burst 50, 1000 global) sit about eleven times above the measured three-session peak per minute and twelve times above the largest burst, so a single developer or a few parallel agents never notice them.
What a 429 means¶
Olla answers a limited request with 429 and a Retry-After header in seconds. On the Anthropic routes the body is Anthropic's error shape, which Claude Code recognises and retries with backoff:
Occasional 429s that clear on retry are the limiter working. Sustained 429s mean the limit is too low for your traffic.
Per-IP or global¶
- Raise
per_ip_requests_per_minute(and usuallyburst_size) when many requests come from one address: several sessions or agents on one machine, a team behind one NAT or VPN exit, CI runners sharing an egress IP, or a reverse proxy that hides client addresses. For the proxy case seetrust_proxy_headersso each client is counted separately. - Raise
global_requests_per_minutewhen the total across all clients is what you hit, for example many users each within their own limit. Set it from what your backends can serve, not from client behaviour.
server:
rate_limits:
per_ip_requests_per_minute: 600 # a team behind one NAT, or many parallel agents
burst_size: 100 # parallel sessions start together
global_requests_per_minute: 6000
Turning limiting off¶
Set both limits to 0 to disable rate limiting entirely. Do this only on a trusted network. The size limits are separate (server.request_limits) and still apply.
Checking whether you are hitting limits¶
/internal/statusreportssecurity.violations.rate_limits(a running count) andsecurity.blocked_ips. The Prometheus metric isolla_security_rate_limit_violations_total.- The log carries a
Rate limit exceededwarning withclient_ip,path,limitandretry_after. It is sampled per client, so a flood produces a summary rather than a line per request. - The
X-RateLimit-Limit,X-RateLimit-RemainingandRetry-Afterresponse headers show the limit a client was held to. TheX-RateLimit-*headers are only sent while a limit applies, so they are absent when rate limiting is off.