Rate limits
z4j applies token-bucket rate limits to public auth paths and to admin paths whose write fan-out can be expensive. Authenticated read paths are not capped.
Per-IP buckets
Section titled “Per-IP buckets”All values are the in-code defaults defined in z4j_brain.domain.ip_rate_limit. The window is 60 seconds.
| Endpoint | Cap (per IP) |
|---|---|
POST /api/v1/auth/login |
20 / min |
POST /api/v1/auth/password-reset/request and /confirm |
10 / min (shared bucket) |
GET /api/v1/invitations/preview and POST /api/v1/invitations/accept |
30 / min (shared bucket) |
| Bulk-write admin actions (bulk-delete tasks, bulk-retry, purge-queue, schedule trigger / import / resync) | 10 / min (shared bucket) |
Notification-channel /channels/test preflight |
20 / min |
| Agent WebSocket connects | dedicated bucket on the /ws endpoint |
Exceeding any limit returns 429 Too Many Requests.
Per-account login lockout (not per-IP)
Section titled “Per-account login lockout (not per-IP)”In addition to the per-IP login bucket, the brain tracks failed logins per account:
| Setting | Default | Meaning |
|---|---|---|
Z4J_LOGIN_LOCKOUT_THRESHOLD |
10 |
Failed attempts before lockout. |
Z4J_LOGIN_LOCKOUT_DURATION_SECONDS |
900 (15 min) |
How long the lockout lasts. |
Z4J_LOGIN_BACKOFF_BASE_SECONDS |
0.5 |
Per-failure incremental backoff applied to the response. |
Z4J_LOGIN_BACKOFF_MAX_SECONDS |
5.0 |
Cap on that backoff. |
Z4J_LOGIN_MIN_DURATION_MS |
(settings) | Minimum response time held server-side so timing is not exploitable. |
The lockout is per-account, so an attacker rotating IPs to evade the per-IP cap still hits the account-level wall.
Response headers
Section titled “Response headers”The brain does not emit X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset today. Detect throttling via the 429 status alone.
Tuning
Section titled “Tuning”Tunables for login lockout and account backoff live in Settings (see above and the env-vars reference). The per-IP bucket sizes are in-code defaults; changing them requires a code change.
Bypass
Section titled “Bypass”/health and /metrics are not rate-limited; scraping is expected.