Rate Limiting
LaunchKit Pro applies in-memory rate limiting on the NestJS API. No Redis is required.
Environment
env
RATE_LIMIT_ENABLED=true
RATE_LIMIT_WINDOW_SECONDS=60
RATE_LIMIT_MAX_REQUESTS=120
RATE_LIMIT_AUTH_MAX_REQUESTS=20
RATE_LIMIT_PUBLIC_API_MAX_REQUESTS=300
RATE_LIMIT_UPLOAD_MAX_REQUESTS=20
RATE_LIMIT_WEBHOOK_MAX_REQUESTS=60
TRUST_PROXY=trueSet RATE_LIMIT_ENABLED=false to disable all tiers (local debugging only).
Tiers
| Tier | Limit (default) | Routes |
|---|---|---|
| default | 120 / 60s | All API routes |
| auth | 20 / 60s | POST /auth/login, register, forgot-password, resend-verification, reset-password, verify-email |
| contact | 120 / 60s | POST /contact/messages, POST /support/tickets |
| upload | 20 / 60s | POST /storage/upload, /profile/avatar, workspace file/logo uploads |
| publicApi | 300 / 60s | GET /public-api/* (API key routes) |
| webhook | 60 / 60s | POST /billing/webhooks/* |
Skipped paths: GET /health, GET /search/status, GET /security/status, OPTIONS.
Client identification
- Unauthenticated: IP from
X-Forwarded-For(whenTRUST_PROXY=true) orreq.ip - Authenticated:
user:{userId}:{tier}when JWT user is present on the request
Response
HTTP 429 with message:
Too many requests. Please try again later.
Retry-After header is set when the window resets.
Nginx / Cloudflare
Enable TRUST_PROXY=true so rate limits use the real client IP from X-Forwarded-For.
Example Nginx proxy headers:
nginx
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;