Skip to main content

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.

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:
  • 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
Formbricks v5 removes application-level rate limiting for several routes that are now expected to be protected by Envoy Gateway. If you self-host Formbricks without Envoy or an equivalent edge rate limiter, those routes will no longer be throttled by the application server after upgrading.
For the full self-hosted upgrade checklist, use this page together with the v5 migration guide.
Rate limits are scoped by identifier, depending on the endpoint and enforcement layer:
  • 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)
When a limit is exceeded, the API returns 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 JSON 429s
For the current source of truth on covered routes and thresholds, use this page together with your deployment configuration and the v5 migration guide.

Envoy-Managed Limits

These limits are expected to be enforced at the gateway layer in Formbricks v5 and later:
Route GroupLimitWindowIdentifier
POST /api/auth/callback/credentials40 requests1 hourIP hash
POST /api/auth/callback/token10 requests1 hourIP hash
GET, POST, PUT, PATCH, DELETE /api/v1/management/* (API key auth only)100 requests1 minuteAPI key ID
POST /api/v1/management/storage (API key auth only)5 requests1 minuteAPI key ID
GET, POST, PUT, PATCH, DELETE /api/v1/webhooks/* (API key auth only)100 requests1 minuteAPI key ID
GET /api/v1/client/[workspaceId]/environment100 requests1 minuteIP hash
POST /api/v1/client/[workspaceId]/responses100 requests1 minuteIP hash
PUT /api/v1/client/[workspaceId]/responses/[responseId]100 requests1 minuteIP hash
POST /api/v1/client/[workspaceId]/displays100 requests1 minuteIP hash
POST /api/v1/client/[workspaceId]/user100 requests1 minuteIP hash
POST /api/v1/client/[workspaceId]/storage5 requests1 minuteIP hash
POST /api/v2/client/[workspaceId]/responses100 requests1 minuteIP hash
PUT /api/v2/client/[workspaceId]/responses/[responseId]100 requests1 minuteIP hash
POST /api/v2/client/[workspaceId]/displays100 requests1 minuteIP hash
POST /api/v2/client/[workspaceId]/storage5 requests1 minuteIP hash
DELETE /storage/[workspaceId]/public/[fileName] (API key auth only)5 requests1 minuteAPI key ID
DELETE /storage/[workspaceId]/private/[fileName] (API key auth only)5 requests1 minuteAPI key ID
Session-authenticated /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:
ConfigLimitWindowIdentifierUsed For
auth.signup30 requests60 minutesIP hashSignup server action
auth.forgotPassword5 requests60 minutesIP hashForgot password server action
auth.verifyEmail10 requests60 minutesIP hashResend verification server action
api.v1100 requests1 minuteSession user IDSession-authenticated v1 management routes, /api/v1/management/me, and /api/v1/integrations/*
api.v2100 requests1 minuteAPI key IDAuthenticated v2 API wrapper outside the Envoy-managed /api/v2/client/* subset
api.v3100 requests1 minuteAPI key ID or session user IDv3 API wrapper
api.client100 requests1 minuteIP hashUncovered client routes such as GET /api/v1/client/og, GET /api/v2/client/[workspaceId]/environment, and POST /api/v2/client/[workspaceId]/user
storage.upload5 requests1 minuteSession user IDSession-authenticated POST /api/v1/management/storage
storage.delete5 requests1 minuteSession user IDSession-authenticated DELETE /storage/[workspaceId]/[accessType]/[fileName]
actions.emailUpdate3 requests60 minutesUser IDProfile email update action
actions.surveyFollowUp50 requests60 minutesOrganization IDSurvey follow-up email processing
actions.sendLinkSurveyEmail10 requests60 minutesIP hashLink survey email send action
actions.licenseRecheck5 requests1 minuteUser IDEnterprise 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-level api.client limiter)
  • GET /api/v2/health (not rate-limited)
  • OPTIONS requests (not rate-limited)

429 Response Shape

Application-generated v1 429s return:
{
  "code": "too_many_requests",
  "details": {},
  "message": "Maximum number of requests reached. Please try again later."
}
Application-generated v2/v3 429s return:
{
  "error": {
    "code": 429,
    "message": "Too Many Requests"
  }
}
Envoy-generated 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:
RATE_LIMITING_DISABLED=1
After changing this value, restart the server. This setting disables only the application-level limiter. It does not disable Envoy rate-limit policies.

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.