SD System Design In Depth
0%
lesson system-designrate-limitingadmission

Rate limiter placement and keys

Module 5.1: Production Reliability, SLOs & Resilience Updated Sep 18, 2026
📄 Cheat Sheet
Inside Stripe's Rate Limiter Architecture
Arpit Bhayani Inside Stripe's Rate Limiter Architecture Watch on YouTube ↗

Arpit breaks down Stripe's production setup: a request-rate limiter, a concurrency limiter and load shedders, what key each one uses and where it runs.

0:00 / --:--

Placement: Edge vs. Gateway vs. Service-Level

  • CDN / Edge: Stops volumetric DDoS attacks before they reach internal cloud infrastructure. Filters by client IP.
  • API Gateway: Protects the overall fleet. Enforces organization-wide rate limits based on API keys, authenticated user IDs, and client tiers.
  • Service-Level: Enforces domain-specific limits (e.g., maximum 5 password reset attempts per email per hour) directly within the service.

Choosing the Rate Limit Key

Rate limiting solely by IP address fails because thousands of mobile users on cellular networks or corporate offices share the same public NAT IP. Effective rate limiting uses composite keys: UserId + Action for authenticated users, and IP + DeviceFingerprint for anonymous endpoints. Client-supplied fingerprints and X-Forwarded-For headers can be forged, so take the IP from your own edge, and key IPv6 clients by prefix (for example /64).

Placement options

LayerKeys availableProtectsLatency costExamples
CDN/edgeIP, ASN, country, path, TLS fingerprintWhole origin against floodsNone added to the originCloudflare rate limiting rules, AWS WAF rate-based rules
API gatewayAPI key, tenant, plan tier, authenticated userFleet fairness and commercial quotasSub-millisecond locally, about 1 ms with a shared RedisEnvoy global rate limit service, Kong, Apigee
ServiceUser + action, resource ID, business fieldsDomain invariants (password resets, SMS sends)Similar to gatewayIn-process limiter backed by Redis
Client of a dependencyDownstream nameA fragile dependency such as a payment processor or partner APILocalConcurrency limits, adaptive limiters (Netflix concurrency-limits)

Worked example: keys for a public API

  • Anonymous GET /search: key ip_prefix + path, 60 per minute. The IPv4 /32 and IPv6 /64 prefixes are computed from the address seen by your edge, not from a header.
  • Authenticated API: key api_key, with the limit set by plan: Free 10 requests per second, Pro 100, Enterprise 1,000. Add a separate per-tenant concurrency limit (for example 20 requests in flight) so a few slow expensive queries cannot tie up every worker.
  • POST /password-reset: two limits must both pass: email at 5 per hour, and ip_prefix at 20 per hour. Together they stop both targeted harassment of one account and broad spraying across many.
  • POST /sms/send: key tenant + destination_country with a daily cost cap. SMS pumping fraud targets expensive destinations.

What Stripe runs in production

Stripe has described four layers: a request-rate limiter (per user, token bucket), a concurrent-requests limiter (caps in-flight requests per user), a fleet usage load shedder (reserves capacity for critical traffic such as charges), and a worker utilisation load shedder (drops low-priority traffic when workers are saturated). The last two do not protect fairness between users. They protect the system as a whole, and they key on the traffic class rather than on a user.

Failure behaviour

flowchart TD R["Request arrives"] --> Q{"Limiter store reachable?"} Q -->|"Yes"| C{"Within limit?"} C -->|"Yes"| A["Allow"] C -->|"No"| D["429 with Retry-After"] Q -->|"No, timeout 5 ms"| F{"Endpoint policy"} F -->|"Fail open"| L["Allow, fall back to a local approximate limit"] F -->|"Fail closed"| D

Most APIs fail open, because the limiter should not become a single point of failure, and they keep a coarse in-memory limit on each instance as a backstop. Security-sensitive endpoints such as login, OTP and payments often fail closed.

Check yourself Question 1 of 3
IPv6 keying recall
From: Choosing the Rate Limit Key

Why does the lesson recommend keying anonymous IPv6 clients by prefix, such as a /64, rather than by full address?

Sliding Window Rate Limiter
Quota: 5 req/sec

Simulate client traffic bursts. If requests exceed 5 requests/sec, subsequent requests are throttled with HTTP 429.

CURRENT 1-SEC WINDOW CAPACITY 0 / 5 Used
// Client Request Stream Output

Key Takeaways

Place rate limiters at multiple tiers: Edge (DDoS), API Gateway (API keys), and Service (business operations).
Avoid IP-only rate limiting due to shared corporate NAT gateways; use composite keys.
Choose fail-open, fail-closed, or a local emergency limit per operation: low-risk reads may degrade open, while login, password reset, spending, and expensive endpoints still need protection when Redis fails.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue