API rate limiting protects your service from abuse, buggy clients, and accidental self-DDoS - without becoming a support nightmare for legitimate users.
Every public or multi-tenant API needs a policy: how many requests, per whom, per window, and what happens at the limit. Pair limits with solid auth (JWT explained) and observability; a throttle alone is not a security program.
Why Rate Limits Exist

Goals:
- Fairness - one noisy tenant cannot starve others
- Cost control - LLM, email, SMS, and DB-heavy routes need tighter caps
- Abuse resistance - credential stuffing, scraping, carding
- Graceful degradation - fail predictably with
429instead of melting the DB
Limits are product decisions. A mobile app's chat sync and an AI "generate report" endpoint should not share one blunt global cap.
Algorithms in Plain Language
| Algorithm | Idea | Good for |
|---|---|---|
| Fixed window | N requests per calendar window | Simple quotas |
| Sliding window | Smooths bursts across window edges | Fairer UX than fixed |
| Token bucket | Refill tokens over time; allow short bursts | APIs with natural spikes |
| Leaky bucket | Steady outflow rate | Smoothing to downstream |
Most HTTP APIs land on token bucket or sliding window counters in Redis (or edge config). Exact choice matters less than consistent keys, clear headers, and tested edge cases.
Where to Enforce
Defense in depth:
- Edge / CDN / API gateway - coarse IP and path limits
- Application middleware - authenticated user/tenant/route limits
- Downstream - per-dependency budgets (OpenAI, Stripe, SMTP)
Do not rely on IP-only limits for authenticated APIs: NAT and mobile carriers punish real users. Prefer API key / user ID / tenant ID as the primary key; keep IP as a secondary signal for anonymous routes.
HTTP Semantics Clients Expect
When limited, return 429 Too Many Requests with:
Retry-After(seconds or HTTP date) when you can- Rate headers such as
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(or IETFRateLimit-*drafts your stack supports)
Document the policy. Silent drops and HTML error pages break SDK retries.
Designing Keys and Quotas

Practical tiers:
- Anonymous - strict, IP + path
- Authenticated - per user
- Tenant / plan - aggregate ceiling for the org
- Expensive routes - separate, lower caps (search, export, AI)
For AI backends, combine HTTP limits with LLM cost controls so token spend cannot bypass request caps.
Redis and Multi-Instance Reality
In-memory counters on one Node process fail as soon as you run two instances. Use a shared store (Redis) or an edge/provider limiter.
Watch:
- Clock skew and window alignment
- Hot keys for popular tenants
- Fail-open vs fail-closed when Redis is down (product risk either way - decide deliberately)
Avoiding False Positives
- Whitelist health checks and internal mesh traffic carefully
- Separate login/auth endpoints (stricter, with lockout/backoff) from read APIs
- Offer higher limits on paid plans - make the policy visible in the dashboard
- Log limit events with user/tenant IDs for support
FAQ: API Rate Limiting
Is rate limiting enough to stop DDoS? No. It helps with application-layer abuse. Volumetric attacks need network/CDN protections.
Should every endpoint share one limit? Usually no. Weight expensive endpoints higher or give them their own bucket.
429 or 503? Use 429 for quota exceeded. Reserve 503 for upstream/capacity failures you want retried differently.
The Bottom Line
API rate limiting best practices are about identity-aware quotas, predictable 429 behavior, and layered enforcement. Start with tenant-aware token buckets on sensitive routes, publish headers, and tune with real traffic - not a single global number copied from a blog comment.
Building multi-tenant APIs that stay fair under load? See Myrafy engineering services or request an estimate.
