Skip to content

Application Rate Limiting

Rate limiting is enforced in Django REST Framework, backed by the configured Redis cache. It does not depend on the external gateway service, so the same limits apply in every deployment topology.

Default Scopes

Scope Identity Rate Applies to Rationale
public_read Client IP 120/min Unauthenticated safe methods Allows mobile bootstrap and public lookup traffic while limiting anonymous scraping bursts.
public_write Client IP 20/min Unauthenticated unsafe methods Protects invite, registration, login, survey, webhook, and Turnstile-gated flows, which are the highest abuse risk seen in Sentry-style repeated failure patterns.
authenticated_read User ID 600/min Authenticated safe methods Read-heavy authenticated screens can make frequent list/detail requests, so this is intentionally higher.
authenticated_write User ID 120/min Authenticated unsafe methods Allows normal operator workflows while limiting accidental loops and scripted write abuse.

Endpoint-Specific Scopes

Scope Identity Rate Applies to Rationale
validate_cooling_user_id_ip Client IP 30/min POST /v1/users/validate-cooling-user-id/ Keeps the existing targeted protection for ID enumeration attempts.
analytics_api_token API token ID 100/min External analytics API Partner integrations are keyed by token rather than user session or IP because many legitimate clients run from shared infrastructure.

Response Shape

When a request is throttled, DRF returns HTTP 429 with a Retry-After header. The application exception handler normalizes the body:

{
  "error": {
    "code": "rate_limited",
    "message": "Request was throttled.",
    "retry_after": 60
  }
}

The rates should be tuned from production telemetry. Repeated validation, registration, login, invite, and other unauthenticated failures should push public_write lower or toward endpoint-specific scopes. Legitimate mobile client bursts should be evaluated before reducing authenticated read/write limits.