Rate Limiting
FormSentry applies rate limiting to every form using a token bucket algorithm, enforced per API key and IP address combination. This protects individual forms from abuse and ensures fair usage.
How It Works
Section titled “How It Works”Each unique combination of API key and IP address gets its own token bucket per form:
- The bucket starts full at
burstcapacity (default: 10 tokens) - Each submission consumes one token
- Tokens refill continuously over
refillWindowseconds (at a rate ofburst / refillWindowtokens per second) - When tokens are exhausted, the request is blocked and returns a
429response - Rate limiting is always enabled and cannot be disabled
The minimum time between requests is enforced at 0.5 seconds (a hard floor of 2 requests per second).
Default Configuration
Section titled “Default Configuration”New forms are created with the following defaults:
| Setting | Default | Description |
|---|---|---|
burst | 10 | Maximum tokens in the bucket (peak capacity) |
refillWindow | 60 seconds | Time to fully refill the bucket from empty |
At the default settings, the refill rate is 10 / 60 = 0.167 tokens per second, meaning a sustained rate of about 10 requests per minute with short bursts up to 10 requests allowed immediately.
Configuration Options
Section titled “Configuration Options”You can adjust rate limiting for each form in the FormSentry web app at app.formsentry.ai/forms
| Setting | Min | Max | Default | Description |
|---|---|---|---|---|
burst | 1 | 50 | 10 | Peak capacity — maximum requests allowed in a short burst |
refillWindow | 10s | 86400s (24h) | 60s | Time to fully refill the bucket from empty |
Refill rate = burst / refillWindow tokens per second. For example:
burst: 10,refillWindow: 60-> 0.167 tokens/sec (10 requests/minute sustained)burst: 5,refillWindow: 30-> 0.167 tokens/sec (same sustained rate, smaller bursts)burst: 20,refillWindow: 60-> 0.333 tokens/sec (20 requests/minute sustained)
Rate Limit Response
Section titled “Rate Limit Response”When a submission is rate limited, the API returns a 429 status:
{ "error": "Rate limit exceeded", "retryAfter": 60, "message": "Too many requests. Please wait before trying again.", "processingTime": 45}Response Headers
Section titled “Response Headers”Every response includes rate limit headers:
X-RateLimit-Limit: 10X-RateLimit-Remaining: 7X-RateLimit-Reset: 1640995200On 429 responses, an additional header is included:
Retry-After: 60| Header | Description |
|---|---|
X-RateLimit-Limit | Burst capacity (maximum tokens in the bucket) |
X-RateLimit-Remaining | Tokens currently available |
X-RateLimit-Reset | Unix timestamp when the bucket will be fully refilled |
Retry-After | Seconds to wait before retrying (429 responses only) |
Handling Rate Limits
Section titled “Handling Rate Limits”Use the Retry-After header to determine how long to wait before retrying:
const response = await fetch('https://api.formsentry.ai/v1/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data)});
if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); console.log(`Rate limited. Retry in ${retryAfter}s`);}Escalation
Section titled “Escalation”FormSentry includes an internal abuse protection mechanism. Repeated violations while already rate limited trigger progressively longer blocks:
| Violations | Block Duration |
|---|---|
| 5+ | 2 minutes |
| 15+ | 10 minutes |
| 30+ | 60 minutes |
Violations decay as legitimate submissions come through, so the escalation resets naturally over time.
See Errors for retry strategies.