Anti-Abuse Protections
Anti-Abuse Protections
Anti-Abuse Protections
Formic includes multiple layers of protection against abuse, automated submissions, and denial-of-service attacks.
Rate Limiting
Rate limiting prevents excessive submissions that could overwhelm the system or exceed email provider quotas.
How It Works
Rate limits are enforced using Redis with atomic INCR/EXPIRE commands in a sliding window. Each form has its own counter keyed as rate_limit:form:{slug}.
Limits
| Limit Type | Default | Purpose |
|---|---|---|
| Per-form | 60 requests/minute | Prevents abuse of a single form |
| Global | 80 requests/minute | Protects email provider quotas |
Both limits are configurable via environment variables (DEFAULT_FORM_RATE_LIMIT and GLOBAL_RATE_LIMIT_PER_MINUTE).
Fail-Closed Behavior
If Redis is unreachable, Formic returns 500 Internal Server Error with the message "Rate limiting service unavailable". This fail-closed approach ensures rate limiting is never accidentally bypassed due to infrastructure issues.
Rate Limit Response
When a rate limit is exceeded, the API responds with:
HTTP 429 Too Many Requests
Retry-After: 60
{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please try again later."
}
The Retry-After header tells clients when to retry. The Formic client library respects this header automatically when retry is enabled.
Cloudflare Turnstile
Turnstile is Cloudflare’s privacy-focused anti-bot alternative to CAPTCHA. Formic requires a valid Turnstile token for every form submission.
How It Works
- Your frontend renders the Turnstile widget and obtains a token
- The token is sent to Formic via the
CF-Turnstile-Tokenheader - Formic validates the token with Cloudflare’s API
- The submission is accepted or rejected based on the result
Client-Side Integration
<!-- HTML form with Turnstile widget -->
<form id="contact-form">
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
<button type="submit">Submit</button>
</form>
<script>
// Using the Formic client with Turnstile
const turnstileToken = turnstile.getResponse();
const result = await client.submit(formData, turnstileToken);
</script>
Server-Side Proxy Integration
When using the server-side proxy pattern, the Turnstile token is forwarded automatically from the incoming request headers:
// The proxy adapter forwards the CF-Turnstile-Token header automatically
export const POST = handleFormicRequest({
apiKey: import.meta.env.FORMIC_API_KEY,
slug: 'contact-form'
});
Turnstile Error Responses
| Status | Meaning |
|---|---|
| 400 Bad Request | Turnstile token is missing or invalid |
| 502 Bad Gateway | Turnstile API is unreachable (2-second timeout) |
Origin Validation
Formic supports per-form origin allow-lists to restrict which websites can submit to a form.
How It Works
Configure allowed_origins on your form configuration:
| Configuration | Behavior |
|---|---|
NULL or empty [] | All origins allowed (backward compatible) |
| One or more origins | Only exact matches allowed |
Origin comparison is case-sensitive and exact (no wildcard or pattern matching).
If the Origin header is absent (common for non-browser requests or same-origin submissions), the request is allowed.
Origin Validation Response
HTTP 403 Forbidden
{
"error": "Forbidden",
"message": "Origin not allowed"
}
Payload Size Limits
Formic enforces a maximum request body size to prevent abuse via oversized payloads.
| Setting | Default | Configurable |
|---|---|---|
| Maximum body size | 2 MB (2,097,152 bytes) | Via MAX_PAYLOAD_SIZE_BYTES env var |
Requests exceeding the limit receive:
HTTP 413 Payload Too Large
{
"error": "Payload Too Large",
"message": "Request body exceeds maximum size of 2097152 bytes"
}
Client-Side Validation
The Formic client library can optionally validate payload size before sending, avoiding wasted bandwidth:
const client = new FormicClient({
apiKey: process.env.FORMIC_API_KEY,
slug: 'contact-form',
validatePayloadSize: true // Check size before sending
});
Related
- Authentication — API key management
- Data Protection — Sanitization and encryption
- Client Usage — Client library configuration