Back to Blog
Blog Post

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.

The Halt Team
#saas#plans#quotas#penalties#multi-tenant
Rate limiting a multi-tenant SaaS: plans, quotas, and penalties

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:

i

Key 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):

c

2. 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:

i

The 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:

i

Three details that make this production-grade rather than a demo:

  1. 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.
  2. Headers as UX. Halt emits RateLimit-Remaining and RateLimit-Reset on every response surface them in your dashboard and customers can self-serve "how much do I have left?" instead of filing tickets.
  3. 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:

n

Dig deeper in the docs: plans, quotas, penalties, and telemetry.