Count the constrained resource
Request-per-minute limits are easy to implement but often miss the real bottleneck. Attackers can choose oversized pages, expensive searches, repeated password messages, or concurrent jobs that consume CPU, memory, storage, provider spend, or human attention.
Define budgets for the resource each operation spends: rows scanned, bytes uploaded, jobs in flight, messages sent, or cost accumulated. Apply limits per user, tenant, token, and meaningful business flow.
Fail predictably
Return a clear error and enough information for a legitimate client to back off. Retry guidance should not reveal sensitive global capacity, and clients should add jitter rather than synchronizing a new traffic spike at the reset boundary.
Enforce hard ceilings server-side even when the interface offers smaller values. Pagination, upload size, execution time, and batch width are all parts of the same resource policy.
- Limit concurrent expensive operations as well as request rate.
- Separate authentication and recovery quotas from general API traffic.
- Set spending limits around paid downstream services.
- Monitor near-limit behavior to tune controls before customers hit them.
Capacity is not authorization
A rate limiter should never substitute for access control. A user under quota can still request an object they do not own, and a privileged automation may need a high rate while remaining tightly authorized.
The best limits express product intent: who may spend which resource, on what action, over which period, and what happens when the budget is exhausted.