Tiered Sliding-Window Rate Limiter
Availability, denial-of-service mitigation, and brute-force prevention are enforced across veridex-hitech-web-application through a custom, distributed MongoDB-backed sliding-window rate limiter (src/lib/rate-limit/).
The limiter operates atomically in the database layer, allowing it to scale across multiple container instances and serverless workers without requiring external Redis clusters.
1. Rate Limit Tier Matrix & Policies
The engine categorizes requests into six distinct operational tiers with tailored thresholds, sliding windows, and resilience policies:
| Category Name | Default Limit | Window Size | Fail-Closed Policy | Target Routes & Operations |
|---|---|---|---|---|
AUTH_STRICT | 5 requests | 15 minutes (900,000 ms) | true (Fail-Closed) | Sign-in authorization, account registration, password reset token validation, OpenAPI docs login. |
FORM_SUBMISSION | 10 requests | 5 minutes (300,000 ms) | false (Fail-Open) | All public forms: Quote drafts, Quote completions, Claims FNOL, Contact Us, Scheduled Calls, Careers. |
AUTHENTICATED_MUTATION | 30 requests | 1 minute (60,000 ms) | false (Fail-Open) | Profile updates, user avatar upload/delete, customer referral invitation creation. |
EXPENSIVE | 10 requests | 1 minute (60,000 ms) | false (Fail-Open) | Heavy analytical queries, failed CRM lead retries, PDF exports, and admin batch processing. |
STANDARD_API | 100 requests | 1 minute (60,000 ms) | false (Fail-Open) | Inbound HMAC partner lead ingestion (/api/leads/*), general interactive dashboard queries. |
READ_ONLY | 200 requests | 1 minute (60,000 ms) | false (Fail-Open) | Public cacheable content fetches, FAQ listings, and public signature streaming (/api/signatures/[id]). |
1.1 Fail-Closed vs. Fail-Open Resilience Strategy
AUTH_STRICT(Fail-Closed): If the MongoDB cluster experiences an intermittent connection failure during a login attempt,AUTH_STRICTblocks the request. This prevents attackers from executing brute-force dictionary attacks during database service interruptions.- Other Tiers (Fail-Open): For form submissions and general browsing, if the rate limiter cannot reach MongoDB, the request is allowed through (
allowed: true). This ensures that genuine human customers filing quotes or claims are never turned away by temporary analytics latency.
2. Identity Resolution & Client Detection
The limiter (getClientIP in src/lib/rate-limit/limiter.ts) determines client identity using a prioritized hierarchy:
- Authenticated User ID: If the user has an active session (
session.user.id), the limiter binds the bucket directly to the account identifier, preventing bad actors from evading limits by rotating IP addresses or VPN tunnels. - Reverse Proxy IP Resolution: For anonymous visitors, the engine parses
x-forwarded-for, extracting the leftmost untampered client IP (stripping intermediate cloud load balancer proxies), with fallback tox-real-ip.
3. Composite Store Key Architecture
Keys stored in the RateLimit collection follow a strict, collision-free composite format:
ratelimit:<category>:<identifier_type>:<identifier_value>:<custom_key>
Examples
- Authentication Attempt:
ratelimit:AUTH_STRICT:ip:203.0.113.195:login:marcus.vance@example.com - Quote Form Submission:
ratelimit:FORM_SUBMISSION:ip:198.51.100.42:quote_submission - Avatar Modification by Logged-In User:
ratelimit:AUTHENTICATED_MUTATION:user:66f4a8b1c2e40001a9b8c7d6:avatar_upload
4. Atomic Increment & TTL Expiration
The rate limiter executes an atomic upsert operation using MongoDB's $inc operator, eliminating race conditions:
// Atomic Rate Limit Evaluation (src/lib/rate-limit/limiter.ts)
const record = await RateLimit.findOneAndUpdate(
{ key: storeKey },
{
$inc: { count: 1 },
$setOnInsert: { resetAt: resetTime },
},
{ upsert: true, new: true }
);
const allowed = record.count <= tier.limit;
const remaining = Math.max(0, tier.limit - record.count);
const retryAfter = allowed ? 0 : Math.ceil((record.resetAt.getTime() - now.getTime()) / 1000);
Automatic TTL Index Eviction
The RateLimit collection defines a Time-To-Live index on resetAt:
RateLimitSchema.index({ resetAt: 1 }, { expireAfterSeconds: 0 });
Once resetAt elapses, MongoDB's background eviction thread automatically removes the document, eliminating database bloat without requiring scheduled cleanup cron jobs.
5. HTTP 429 Response & User Feedback
When a client breaches their designated limit:
- API Routes: Return HTTP 429 with standard headers:
HTTP/1.1 429 Too Many RequestsContent-Type: application/jsonRetry-After: 480X-RateLimit-Limit: 5X-RateLimit-Remaining: 0X-RateLimit-Reset: 1729267200
- Server Actions & UI: Return a localized error message:
"We've received too many requests from you recently. Please try again in a few minutes."