Benefits of Per-User Usage Caps for AI Features
Picture a free-tier user who points a script at your AI feature and goes to bed. You find out when the invoice arrives.
Per-user usage caps, a token or request quota that each user (or tenant) gets per day or month, are the cheapest way to stop that. Below are five benefits, a quota check you can adapt, and the cases where caps hurt more than they help.
Five benefits of per-user usage caps
1. Your worst-case bill has a ceiling. Without caps, spend is whatever your most enthusiastic user decides it is. With them, the worst case is users times cap times price per token. Say you have 1,000 free users on a 50,000-token monthly cap: the free tier tops out at 50 million tokens, and you can multiply that by your model's price before you ship. Provider limits don't do this job for you. Anthropic's rate limits docs describe spend and rate limits at the organization and workspace level, which know nothing about your individual users. Keep the organization limit as a backstop and put the per-user cap in front of it.
2. A few heavy users or scripts can't starve everyone else. Usage is rarely spread evenly, and a handful of accounts usually account for most of it (check your own logs). A token quota per user, plus a small requests-per-minute limit, keeps a runaway script from eating the month's budget in an afternoon. It also gives you an abuse signal: an account that burns its cap in hours is worth a look. Send a stable per-user ID to your provider as well. OpenAI's safety identifier exists so abuse can be traced to one user instead of your whole app.
3. You get real data for pricing tiers. Guessing tier sizes is how you end up with a free plan that's too generous and a paid plan nobody needs. Once caps exist, you log how much of the cap each user burns. Sort by that and the breakpoints show up: the median user, the 90th percentile, and the people who keep hitting the wall. GitHub Copilot's billing docs describe the same shape, a per-user monthly allowance of premium requests on each plan, with usage beyond it billed as overage.
4. Upgrade prompts land at the moment of need. A user at 80% of their cap is mid-task and invested. A message saying they've used 80% of this month's AI allowance, with an upgrade link, is a better-timed upsell than a banner on a pricing page. The snippet below returns that link for exactly this reason.
5. Tenant quotas make B2B contracts easier. Cap per tenant as well as per user, and a contract line like 2 million tokens a month, then pay as you go, is something sales can sell and finance can forecast. The customer's admin sees the meter instead of arguing with the invoice.
A token quota per user in about 30 lines
This sketch keeps a monthly token counter per user in Redis, checks it before the model call, and records actual usage afterwards. It uses redis-py.
import time
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
# Monthly token caps per tier. Placeholder numbers: set yours from real usage data.
TIER_CAPS = {'free': 50_000, 'pro': 1_000_000}
MAX_OUTPUT_TOKENS = 1_000
WARN_AT = 0.8
def quota_key(user_id: str) -> str:
month = time.strftime('%Y-%m', time.gmtime())
return f'quota:{user_id}:{month}'
def tokens_used(user_id: str) -> int:
return int(r.get(quota_key(user_id)) or 0)
def record_usage(user_id: str, tokens: int) -> int:
key = quota_key(user_id)
pipe = r.pipeline()
pipe.incrby(key, tokens)
pipe.expire(key, 35 * 24 * 3600) # old months expire on their own
new_total, _ = pipe.execute()
return new_total
def handle_request(user_id: str, tier: str, prompt: str) -> dict:
cap = TIER_CAPS[tier]
used = tokens_used(user_id)
estimate = len(prompt) // 4 + MAX_OUTPUT_TOKENS # rough: about 4 characters per token
if used + estimate > cap:
log_event('quota_exceeded', user_id=user_id, tier=tier, used=used, cap=cap)
return {'status': 429, 'error': 'quota_exceeded', 'used': used, 'cap': cap, 'upgrade_url': '/pricing'}
response = call_model(prompt, max_tokens=MAX_OUTPUT_TOKENS)
total = record_usage(user_id, response.input_tokens + response.output_tokens)
return {'status': 200, 'answer': response.text, 'quota_warning': total >= WARN_AT * cap}
call_model and log_event stand in for your model client and analytics. Swap in your provider's usage fields, since names differ between APIs. The quota_exceeded event is the upgrade-demand data from benefit 3, so don't skip it. The check and the increment aren't atomic, so concurrent requests can overshoot by a few calls. That's fine for a soft cap. For a hard cap, reserve tokens up front with a Lua script or INCRBY and refund the difference afterwards.
When per-user usage caps are not worth it
- Launch week. When adoption is the goal, a tight cap punishes your most enthusiastic users just as word of mouth builds. Set caps generously, or use soft caps: warn first, then fall back to a cheaper model instead of blocking.
- Small, trusted audiences. If 40 people on an internal tool cost less per month than the engineer-hours to build quotas, a billing alert is enough.
- Long jobs. A cap that cuts a user off halfway through a task leaves a worse impression than a slightly higher bill. Check against an estimate before starting, as the snippet does, rather than failing midstream.
A cap is a pricing decision written in code, and an AI feature in production without one has its bill set by whoever uses it hardest.