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:
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.