Skip to main content
The NSP daemon applies token-bucket rate limiting to every API key independently. Each key gets its own bucket for state reads, action execution, and heap snapshots. When a bucket empties, the daemon returns a 429 response until the bucket refills — it never queues or delays requests on your behalf. Rate limiting is on by default, applies globally across all API routes, and is one of the most effective guardrails against runaway agent loops eating into your system resources.

Default Rate Limits

These limits apply per API key. A single agent using one key is subject to all three buckets simultaneously.
Heap snapshots are the most resource-intensive operation the daemon performs — a full V8 heap snapshot can take up to 47 seconds. The default limit of 2 per minute is intentionally conservative and should rarely need increasing.

When You Are Rate Limited

When a request exceeds your configured limit, the daemon immediately returns an HTTP 429 with a Retry-After header telling you how many seconds to wait before retrying:

Handling 429 in the Python SDK

The SDK does not retry automatically — you control the retry logic so your agent’s behavior remains predictable. Here is a simple exponential back-off pattern:

Configuring Rate Limits

Set your limits in the [rate_limit] section of axon.toml. All limits are per-API-key.
Start with action_per_second lower than you think you need — for example 3 or 5 — and raise it only when profiling shows your agent legitimately requires more throughput. A lower action limit reduces the blast radius of any agent logic bug that triggers a tight execution loop.

Environment Variable Equivalents

Every [rate_limit] key maps to an AXON_RATE_LIMIT__* environment variable. Environment variables always take precedence over axon.toml values. Example — tightening action limits in a CI environment without modifying axon.toml:

Recommendations

Set action_per_second conservatively. Action execution touches a live runtime probe, may trigger UI-level effects, and has real-world consequences. A limit of 35 is a reasonable starting point for most agents. Reserve higher limits for batch workflows you have explicitly profiled. Use WebSocket watch instead of polling state. If your agent reacts to state changes, subscribe to the WebSocket stream with GET /substrate/v1/watch instead of polling GET /state on a timer. A WebSocket subscription uses zero rate-limit budget between change events, while a 10 Hz polling loop consumes 10 of your 100 reads-per-second budget every second, even when nothing changes. Disable rate limiting only in isolated test environments. The rate_limit.enabled = false setting is useful in CI pipelines where you control all traffic, but always run with rate limiting enabled when connected to production applications.
Setting AXON_RATE_LIMIT__ENABLED=false removes all throttling from every endpoint. Only use this in isolated test environments where you can guarantee no production data or real-world side effects are reachable.