Formbricks applies request rate limits to protect against abuse and keep API usage fair. Starting with Formbricks v5, rate limiting is split across two layers:Documentation Index
Fetch the complete documentation index at: https://formbricks.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
- Envoy Gateway for public and API-key routes that can be enforced at ingress
- The application server for remaining session-authenticated routes, server actions, and other flows Envoy does not currently cover
For the full self-hosted upgrade checklist, use this page together with the
v5 migration guide.
- IP hash (for unauthenticated/client-side routes and public actions)
- API key ID (for Envoy-managed and app-managed authenticated API calls)
- User ID (for authenticated session-based calls and server actions)
- Organization ID (for follow-up email dispatch)
429 Too Many Requests.
v5 Migration Note
Before upgrading to Formbricks v5:- deploy Envoy Gateway or an equivalent edge rate limiter for the covered routes below
- keep application Redis/Valkey enabled for the remaining app-enforced limits
- expect covered routes to emit gateway
429s instead of the legacy app JSON429s
Envoy-Managed Limits
These limits are expected to be enforced at the gateway layer in Formbricks v5 and later:| Route Group | Limit | Window | Identifier |
|---|---|---|---|
POST /api/auth/callback/credentials | 40 requests | 1 hour | IP hash |
POST /api/auth/callback/token | 10 requests | 1 hour | IP hash |
GET, POST, PUT, PATCH, DELETE /api/v1/management/* (API key auth only) | 100 requests | 1 minute | API key ID |
POST /api/v1/management/storage (API key auth only) | 5 requests | 1 minute | API key ID |
GET, POST, PUT, PATCH, DELETE /api/v1/webhooks/* (API key auth only) | 100 requests | 1 minute | API key ID |
GET /api/v1/client/[workspaceId]/environment | 100 requests | 1 minute | IP hash |
POST /api/v1/client/[workspaceId]/responses | 100 requests | 1 minute | IP hash |
PUT /api/v1/client/[workspaceId]/responses/[responseId] | 100 requests | 1 minute | IP hash |
POST /api/v1/client/[workspaceId]/displays | 100 requests | 1 minute | IP hash |
POST /api/v1/client/[workspaceId]/user | 100 requests | 1 minute | IP hash |
POST /api/v1/client/[workspaceId]/storage | 5 requests | 1 minute | IP hash |
POST /api/v2/client/[workspaceId]/responses | 100 requests | 1 minute | IP hash |
PUT /api/v2/client/[workspaceId]/responses/[responseId] | 100 requests | 1 minute | IP hash |
POST /api/v2/client/[workspaceId]/displays | 100 requests | 1 minute | IP hash |
POST /api/v2/client/[workspaceId]/storage | 5 requests | 1 minute | IP hash |
DELETE /storage/[workspaceId]/public/[fileName] (API key auth only) | 5 requests | 1 minute | API key ID |
DELETE /storage/[workspaceId]/private/[fileName] (API key auth only) | 5 requests | 1 minute | API key ID |
/api/v1/management/*, /api/v1/management/me, /api/v1/management/storage, and
DELETE /storage/... requests are not covered by the current Envoy policies and remain app-enforced.
App-Enforced Limits
These are the limits that still run inside the Formbricks application server:| Config | Limit | Window | Identifier | Used For |
|---|---|---|---|---|
auth.signup | 30 requests | 60 minutes | IP hash | Signup server action |
auth.forgotPassword | 5 requests | 60 minutes | IP hash | Forgot password server action |
auth.verifyEmail | 10 requests | 60 minutes | IP hash | Resend verification server action |
api.v1 | 100 requests | 1 minute | Session user ID | Session-authenticated v1 management routes, /api/v1/management/me, and /api/v1/integrations/* |
api.v2 | 100 requests | 1 minute | API key ID | Authenticated v2 API wrapper outside the Envoy-managed /api/v2/client/* subset |
api.v3 | 100 requests | 1 minute | API key ID or session user ID | v3 API wrapper |
api.client | 100 requests | 1 minute | IP hash | Uncovered client routes such as GET /api/v1/client/og, GET /api/v2/client/[workspaceId]/environment, and POST /api/v2/client/[workspaceId]/user |
storage.upload | 5 requests | 1 minute | Session user ID | Session-authenticated POST /api/v1/management/storage |
storage.delete | 5 requests | 1 minute | Session user ID | Session-authenticated DELETE /storage/[workspaceId]/[accessType]/[fileName] |
actions.emailUpdate | 3 requests | 60 minutes | User ID | Profile email update action |
actions.surveyFollowUp | 50 requests | 60 minutes | Organization ID | Survey follow-up email processing |
actions.sendLinkSurveyEmail | 10 requests | 60 minutes | IP hash | Link survey email send action |
actions.licenseRecheck | 5 requests | 1 minute | User ID | Enterprise license recheck action |
Explicit Envoy Exclusions
The current Envoy policy set explicitly excludes these routes:GET /api/v1/client/og(still covered by the app-levelapi.clientlimiter)GET /api/v2/health(not rate-limited)OPTIONSrequests (not rate-limited)
429 Response Shape
Application-generated v1429s return:
429s return:
429s are gateway responses and should include an x-envoy-ratelimited header. Their exact body
shape is not the same stability contract as the in-app JSON responses above.
Disabling Rate Limiting
For self-hosters, rate limiting can be disabled if necessary. We strongly recommend keeping it enabled in production. Set:Operational Notes
- Redis/Valkey is required for the application-level limiter (
REDIS_URL). - If you deploy Envoy rate limiting, use a dedicated Redis/Valkey backend for Envoy instead of sharing the app cache.
- If application Redis is unavailable at runtime, app rate-limiter checks currently fail open (requests are allowed through without enforcement).
- Client storage upload rate limits count signed upload URL issuance, not successful object creation in S3-compatible storage.
- Authentication failure audit logging uses a separate throttle (
shouldLogAuthFailure()) and is intentionally fail-closed: when Redis is unavailable or errors occur, audit log entries are skipped entirely rather than written without throttle control. This prevents spam while preserving the hash-integrity chain required for compliance. In other words, if Redis is down, no authentication-failure audit logs will be recorded—requests themselves are still allowed (fail-open rate limiting above), but the audit trail for those failures will not be written.