Rate limiting a multi-tenant SaaS: plans, quotas, and penalties
Free users get 100 requests an hour, Pro gets 10,000, and one abusive key shouldn't ruin anyone's day. How to model real SaaS pricing tiers with Halt.
Rate limiting a multi-tenant SaaS
A single global limit is fine for a weekend project. The moment you have pricing tiers, rate limiting becomes part of your product: limits are what customers buy. That changes the requirements in three ways.
1. Limits follow the plan, not the route
The same POST /v1/search call should cost a Free user differently than an Enterprise customer. With Halt you resolve the policy from the authenticated tenant, not the URL:
iKey the limiter by API key or tenant ID (never by IP corporate NATs would let one office exhaust a whole plan, and one tenant could run many IPs):
c2. Quotas are limits with a longer memory
Per-minute limits protect your infrastructure; quotas enforce what the customer paid for "1M requests per month" is a quota, not a rate. Halt tracks both simultaneously, on hourly, daily, monthly, or yearly horizons:
- the rate limit answers "is this client hammering us right now?"
- the quota answers "has this tenant used up their plan?"
A request must pass both. The nice property: quota state lives in the same store as the counters, so you don't need a separate metering pipeline to launch usage-based pricing.
3. Penalties for the persistently abusive
Most 429s are honest bugs a retry loop without backoff. But a client that keeps slamming you after being told to stop deserves an escalating response. Halt's penalty system tracks repeat offenders per key and applies progressive cool-downs:
iThe escalation is automatic and self-healing: behave for a while and the penalty decays. Your support team never has to manually un-ban anyone.
Putting it together
A realistic multi-tenant setup is still only a few lines:
iThree details that make this production-grade rather than a demo:
- A shared store. With several API instances behind a load balancer, in-memory counters silently multiply every limit by the instance count. Use a distributed backend in production.
- Headers as UX. Halt emits
RateLimit-RemainingandRateLimit-Reseton every response surface them in your dashboard and customers can self-serve "how much do I have left?" instead of filing tickets. - Telemetry hooks. Pipe allow/block decisions into your metrics stack. A spike in 429s on the Free tier is a sales signal, not just an ops one.
Start with the presets
The built-in plan presets (FREE through ENTERPRISE) are sane starting points you can override per tenant later:
nDig deeper in the docs: plans, quotas, penalties, and telemetry.