Problem: AI API calls cost money. Without limits, a single user could run up significant costs. BibleWeb needs to control AI usage per user while still providing a generous experience for paying customers.
Solution: Two-layer rate limiting: a per-minute spam guard (20 req/min) and a daily quota tied to the user's subscription tier. Beta codes grant temporary access with specific limits.
Not included: Per-query cost tracking or billing (that's the Cost Tracking feature). This is about limiting the number of requests, not tracking their cost.
Tier limits:
| Tier | Daily Limit | Access |
|---|---|---|
| Free | 0 (blocked) | No AI access |
| Beta Low | 5/day | Beta code: "beta" or "uitproberen" |
| Beta High | 20/day | Beta code: "vriend" or "friend" |
| Admin | 999/day | Admin users |
User experience:
Per-minute guard: 20 requests per minute per IP — prevents rapid-fire abuse regardless of tier.
Edge cases:
ask_daily:${userId or IP} — authenticated users track by user ID, anonymous by IPMap<string, { count, resetAt }>, cleaned up every 60 secondsapp_metadata.beta_tier or cookie fallbackError display: When rate limited, the chat shows an error message explaining the daily limit and when it resets.
No visible counter — users don't see remaining questions (could be added later).
Rate limiter (apps/web/src/lib/server/rate-limit.ts):
Map<string, { count, resetAt }>/api/ask:Tier limits (apps/web/src/lib/server/beta-codes.ts):
getAiDailyLimit(betaTier) returns the numeric limit'vriend'/'friend' → beta_high, 'beta'/'uitproberen' → beta_lowCleanup: setInterval every 60 seconds removes expired entries from the Map.
Files:
apps/web/src/lib/server/rate-limit.ts — rate limiter implementationapps/web/src/lib/server/beta-codes.ts — tier limits + beta code mappingapps/web/src/routes/api/ask/+server.ts — applies both rate limit checksCurrent: DONE Milestone: v3 Priority: Core — essential for cost control
History:
Dependencies: