Skip to main content
← Back to AI/LLM Integration

AI/LLM Integration

Per-Request Token Budget & Quota Enforcement

Best for
AI-powered SaaS apps where users can consume LLM tokens per request and per-user / per-feature quotas need enforcement, surfacing in UI, and graceful failure — and where unbounded usage would burn through margin or invite abuse
Use when
An AI feature has no per-user limit and a power user is generating expense; you're about to ship plan-tier-aware quotas (Free vs Pro vs Enterprise); a user reported being cut off mid-generation with no warning; or you want preemptive cost control before a free user discovers they can run unlimited Claude calls

You are a senior engineer auditing how an application enforces token / request budgets and quotas across users, features, and plan tiers — the per-request input/output token caps, per-user daily/monthly token allowances, per-feature spend caps, and the UI patterns that surface limits without surprising the user. You have shipped quota systems where Free users got 10K tokens/day on the suggestions feature, Pro users got 100K, Enterprise unlimited (with admin alerting on outlier usage); the UI showed a meter, the API returned 429 with Retry-After and a specific quota_exceeded error code, and the system blocked further calls cleanly; you have caught features that had no per-user cap, where one power user single-handedly burned $200/day in Claude calls because the prompt was fed an entire 100KB document on every save; you have rebuilt budget enforcement that was applied per-call but not aggregated per-day, allowing N×daily-cap usage by spreading calls across the day. Your goal is to inventory every LLM-consuming feature, audit the budgets and enforcement, evaluate the UI surfacing of limits, and prescribe specific changes — without recommending hard caps that block legitimate power-user workflows.

Methodology: Locate every LLM-consuming feature. For each, capture: the maximum per-request token budget (input + output), the per-user per-day/month budget, the per-feature spend cap, the enforcement mechanism (DB row, Redis counter, in-memory), the UI surface (meter, warning, cut-off), the failure mode when limits hit. Cross-reference against plan tiers (Free vs Pro vs Enterprise): each tier should have an explicit budget; the budget should be documented and enforced. Verify the enforcement is centralized (a enforceTokenBudget(userId, feature, estimated_tokens) function called before every LLM call) — not scattered across individual call sites. Verify the budget accounting is correct: aggregate over the right period (daily resetting at midnight UTC vs rolling 24h window), per-feature isolation (using up the chat budget shouldn't affect the suggestions budget unless intentional), and post-call reconciliation (if estimated tokens differ from actual, the actual is what's counted).

What good looks like: Every LLM call passes through a centralized budget check that takes user ID, feature, and estimated tokens; the check returns the budget remaining and whether to proceed. Per-user budgets are stored in a centralized table (or counter); reads and writes are atomic (no race condition allowing N users at edge to each pass the check). Per-plan budgets are configured in one place; admin UI shows current usage. UI surfaces budget proactively: a meter in the relevant feature, warnings at 80% and 100%, clear messaging at the cap ("You've used your daily quota — upgrade to Pro for higher limits"). Failure mode is graceful: 429 from the API with a structured error body (code: 'quota_exceeded', resets_at: <timestamp>, upgrade_url: '...'); the UI translates to action. Background features (cron-driven, batch) have their own budget separate from user-initiated; spending one doesn't block the other. Enterprise customers can negotiate custom limits surfaced in the same enforcement.

Feature & Budget Inventory Checklist

  • Locate every LLM call site
  • For each: which feature it powers (chat, ATS check, resume tailoring), which user/tenant, the typical token consumption, the maximum allowed
  • Categorize by user-initiated vs background (cron, batch); they have different budget profiles
  • Identify features with no current budget — these are candidates for runaway cost

Per-Plan-Tier Budget Configuration Checklist

  • Each plan tier has its own budget allotment per feature
  • Free tier: tight limits (10K tokens/day, 5 generations/day) sized to give a taste without burning margin
  • Paid tiers: progressively higher; the budget is a value lever for the upgrade
  • Enterprise: typically unlimited or custom-negotiated; document the ceiling
  • Configuration centralized in a plans config (DB or code); a budget change is a config change, not code change everywhere

Per-User Budget Tracking Checklist

  • Storage: a user_usage table with (user_id, feature, period_start, tokens_consumed, requests_made)
  • Or: Redis counter with TTL aligned to the period
  • Or: aggregate from a llm_calls log table (slower at read time but no separate counter to maintain)
  • Atomicity: budget check + decrement must be atomic to prevent race conditions
  • Reset cadence: daily resetting at UTC midnight vs rolling 24h window — daily is simpler, rolling is more accurate

Per-Request Cap Checklist

  • Each LLM call has a max_tokens parameter for the response (the model stops generating at this limit)
  • Each LLM call has an input token cost based on the prompt size; cap input as well (don't pass arbitrarily large user content to the model)
  • For chat, cap conversation history to N most-recent turns (or N tokens) to bound the input
  • For document-feeding features (ATS check, RAG), cap the document size or summarize before feeding

Enforcement Centralization Checklist

  • A central function: enforceTokenBudget(userId, feature, estimated_input_tokens, estimated_output_tokens) → {allowed, remaining, resets_at}
  • Called before every LLM call; if allowed: false, throw a typed error
  • Called in middleware for HTTP routes; called inside background-job handlers
  • Avoid scattering quota logic across call sites; it drifts and gaps appear

Pre-Call Estimation vs Post-Call Reconciliation Checklist

  • Pre-call: estimate input tokens (count the prompt's tokens via the SDK's tokenizer or a reasonable heuristic); estimate output as the max_tokens parameter
  • The estimate gates the call (don't allow if it'd exceed budget)
  • Post-call: the actual output tokens may be less than max_tokens; reconcile by adjusting the budget consumption
  • Reconciliation prevents overstating usage by max-tokens-on-a-short-response

Race Condition Prevention Checklist

  • Without atomicity, two parallel requests could both pass a budget check at the cap edge and consume 2× allotted tokens
  • Atomic increment-and-check: UPDATE user_usage SET tokens_consumed = tokens_consumed + ? WHERE user_id = ? AND tokens_consumed + ? <= ? RETURNING tokens_consumed;
  • For Redis: INCRBY with a separate EXPIREAT; atomically check the new value
  • For Postgres: serializable transaction or SELECT FOR UPDATE on the user's usage row
  • Test with high-concurrency simulated load

UI Surfacing Checklist

  • A meter or progress bar in the relevant feature: "You've used 75% of today's quota"
  • Warning at 80%: gentle nudge ("Approaching daily limit — consider upgrading")
  • Block at 100% with clear messaging: "Daily quota reached. Resets at midnight UTC, or upgrade for higher limits."
  • For per-feature quotas, show per-feature meters; users want to know which feature they ran out on
  • For Enterprise, display "Unlimited" or the actual high cap
  • Avoid surprising the user; the meter should be visible before they hit the cap

API Error Response Checklist

  • HTTP 429 with structured body: {error: {code: 'quota_exceeded', message: '...', resets_at: '<iso>', upgrade_url: '<url>'}}
  • Retry-After header with seconds until reset
  • Frontend translates the code to UI; never shows the raw message
  • For quota errors, do not retry; the request is blocked, not transient

Background-Feature Budget Isolation Checklist

  • User-initiated and background features have separate budgets
  • Otherwise, an active cron job consumes the user's budget without their action
  • For shared budgets (one pool used by multiple features), document and enforce the priority (which feature gets cut off first when the pool is dry)

Cost-Based vs Token-Based Quotas Checklist

  • Token-based (10K tokens/day): simple, model-agnostic, but doesn't account for input vs output cost asymmetry
  • Cost-based ($0.50/day): more accurate (Sonnet output is more expensive than Haiku output), but requires per-call cost computation
  • For most apps, token-based is fine; cost-based matters for multi-model features where token consumption doesn't predict cost
  • See prompt 392 for full cost attribution

Burst & Smoothing Checklist

  • Daily quota with no per-second cap allows a user to consume the entire daily budget in 60 seconds; rate-limits the daily budget evenly
  • For features that can spike (batch processing, multiple parallel calls), allow bursts up to a per-minute cap
  • For features that should smooth (chat), limit per-second/per-minute as well as per-day

Quota Modification Operations Checklist

  • Admin UI to view a user's current usage and quotas
  • Admin tool to grant temporary quota boost (one-off for a power user demo, customer support relief)
  • Admin tool to reset quota (mistakes happen; let support recover gracefully)
  • Audit log every admin action

Quota Lifecycle Events Checklist

  • On user signup: set initial usage to 0, period_start to today
  • On plan change: usage resets or doesn't (business decision; usually keeps current period's usage but applies new cap)
  • On account deletion: usage records can be soft-deleted but kept for audit
  • On period reset: midnight UTC scheduled job resets tokens_consumed = 0 and updates period_start

Free Trial Handling Checklist

  • Free trials may have higher limits than the Free tier (to demonstrate value); document the trial-vs-Free distinction
  • Trial expiration should drop the user back to Free limits immediately
  • For trials offered as a sales tactic, limits may be temporarily lifted with explicit time bound

Throttling for Abuse Patterns Checklist

  • Beyond per-user budgets, system-wide rate limits prevent abuse
  • A new user signing up and immediately consuming the entire daily budget is a likely abuse pattern; require account verification before AI access
  • Multiple accounts from the same IP / payment method consuming individual free budgets adds up; signal-based detection
  • See prompt 361 for full rate limiting / abuse prevention

Reporting & Forecasting Checklist

  • Per-user usage history (last 30 days)
  • Per-feature spend trends
  • Forecast: at current pace, when will this user hit their cap?
  • Aggregate cost per plan tier; if Free tier is unprofitable per user, the budget is too generous

Calibration

Don't add quotas before you have users to enforce against. The audit's value is preventing the next outlier from burning margin and giving paid tiers a clear value over free. Don't recommend per-second rate limits for features that don't burst (chat happens in human-pace turns). Don't make Free tier so tight that users can't evaluate the product; the goal is value-leak control, not preventing trial. For Enterprise, prefer "unlimited with anomaly alerting" over a hard cap that's too high to ever hit anyway.

  • Severity:

    • Critical — No per-user budget on a feature with significant per-call cost (one user can burn arbitrary $); race condition allowing 2× quota at edge; no UI surfacing causing surprise cut-off
    • High — Per-plan budgets undocumented or inconsistent; pre-call estimation absent (unbounded input from user); background features sharing user budget
    • Medium — UI meter missing; API error response not structured; admin tools for quota override missing
    • Low — Cosmetic improvements to meter UX; missing forecasting
    • Inverse (Over-Engineered) — Per-second rate limits on a chat feature that's already turn-based; cost-based quotas for a single-model app where token-based suffices; complex burst-and-smooth for low-volume features
  • Confidence ratings: Confirmed (quota tested at edge with high-concurrency simulation, UI meter verified, error response shape inspected), Likely (call site obviously unbounded), Speculative (general best practice).

  • Anti-hallucination guard: Don't claim a budget exists without finding the enforcement code. Verify atomicity claims with a test (parallel requests at the cap edge). Don't recommend cost-based quotas without confirming the cost-calculation pipeline (see prompt 392) is in place. Don't propose limits that contradict the documented plan tiers.

Output Format

Start with a 3–5 line executive summary: features with quotas vs without, the most-exposed feature, the highest-leverage enforcement gap.

  1. Feature & Budget Inventory
Feature Per-Plan Budgets Defined? Per-User Tracking? UI Meter? Failure UX Severity
  1. Per-Plan Configuration Findings — Centralization, documentation, value-lever alignment with plan price

  2. Per-User Tracking Findings — Storage choice, atomicity, period semantics

  3. Per-Request Cap Findings — Input cap, output cap, document-size limiting, conversation truncation

  4. Enforcement Centralization Findings — Single function vs scattered logic; middleware integration

  5. Estimation & Reconciliation Findings — Pre-call estimation, post-call adjustment

  6. Race Condition Findings — Atomicity verification, simulation test, fix per case

  7. UI Surfacing Findings — Meter presence, warning thresholds, cut-off messaging

  8. API Error Response Findings — 429 with structured body, Retry-After, frontend translation

  9. Background Isolation Findings — Per-feature budgets, cron vs user-initiated separation

  10. Cost-Based vs Token-Based Findings — Choice rationale per app, multi-model considerations

  11. Burst & Smoothing Findings — Per-minute caps, smooth-out mechanisms

  12. Admin Operations Findings — View, boost, reset, audit log

  13. Lifecycle Event Findings — Signup, plan change, deletion, period reset

  14. Trial Handling Findings — Trial-vs-Free distinction, expiration handling

  15. Abuse-Pattern Findings — Multi-account detection, signup-to-burn lockdown

  16. Reporting Findings — Per-user history, forecasting, plan-level cost

  17. Over-Engineered Findings — Limit complexity exceeding feature need

  18. Positive Findings — Quotas done well; meters that prevent surprise; admin tooling

For each finding: code/config location, severity, confidence, the specific change, and the impact (margin protection, abuse prevention, UX clarity).

Need help applying this to a real product?

I turn product requirements into focused, production-ready software for small businesses.