Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

System Design blueprint · Public APIs

API rate limiter

A token bucket in front of the API keeps one noisy client from starving everyone else.

Steps
6
Subjective questions
32
Objective questions
32

The problem and the outcome

Problem: One buggy client or scraper can exhaust capacity for every other customer.

Outcome: Fair usage per key, with clear 429 errors instead of outages.

Architecture

ClientAPI key / IP01API gateway02Rate limitertoken bucket03Rediscounters per key04Ruleslimits per planBackendservice05429 Too ManyRequests06take tokenload limitsallowedempty bucketRetry-After

How it works, step by step

  1. Every request carries a key: a user ID, an API key or an IP address.
  2. The gateway runs the limiter before any business code.
  3. Token bucket: each key holds N tokens that refill at a fixed rate; the limits come from config per plan.
  4. Redis keeps the counters and updates them atomically (INCR or a Lua script), so every server sees one count.
  5. A request that gets a token goes through to the service.
  6. An empty bucket returns 429 with a Retry-After header.

Tech stack

  • API gateway (Kong, Envoy, AWS API Gateway)
  • Redis with Lua scripts
  • Config service for plan limits
  • Retry-After and X-RateLimit headers

Key design decisions

  • Token bucket: it allows short bursts up to the bucket size while holding the long-run rate steady.
  • Shared counters in Redis, updated atomically with a Lua script, so every gateway node sees the same count.
  • Limit per API key or user, not only per IP, so customers behind one office NAT do not block each other.

Common mistakes

  • Read-then-write counters without atomicity, so concurrent requests slip past the limit.
  • Fixed one-minute windows that let a client send double the limit across a window boundary.
  • Failing closed when Redis is down and taking the whole API offline with it.

What to measure

  • 429 rate per plan and per key
  • Limiter overhead per request (should be about a millisecond)
  • Top keys by rejected requests

Most-asked interview questions

Subjective questions 32

1Compare token bucket, leaky bucket, fixed window and sliding window.Asked almost every time

Fixed window counts per clock minute; it is cheap but allows a burst of twice the limit at the boundary. Sliding window (a log or a weighted counter) smooths that edge. Token bucket refills tokens at a fixed rate and allows bursts up to the bucket size. Leaky bucket drains a queue at a constant rate, so output is smooth but requests wait. Token bucket is the usual default for public APIs.

2Where should a rate limiter run in a system?Asked almost every time

As close to the edge as possible: in the API gateway or a middleware layer, so rejected requests do not consume backend resources. Different layers can limit differently: per IP at the CDN or WAF, per API key or user at the gateway, and per tenant or resource deeper in services.

3How does a sliding window log differ from a sliding window counter?Asked almost every time

A sliding window log stores each request's timestamp (for example in a sorted set) and counts those within the last window: precise but memory-heavy. A sliding window counter keeps counts for the current and previous fixed windows and weights the previous one by overlap: approximate but cheap.

4How would you implement a token bucket in Redis?Asked almost every time

Store tokens and the last refill time per key. On each request, a Lua script calculates tokens added since the last refill (rate × elapsed), caps at capacity, subtracts one if available and saves the new state atomically, returning allowed or denied plus remaining tokens.

5How do you rate-limit consistently across many gateway servers?Very often asked

Keep the counters in a shared store such as Redis and update them atomically: INCR with an expiry, or a Lua script that refills and takes a token in one step. For very high traffic, each node can take a small local allowance and sync it periodically, accepting a little inaccuracy for speed.

6What should a rate-limited response contain?Very often asked

Status 429 Too Many Requests, a Retry-After header saying when to retry, and rate-limit headers such as RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset so well-behaved clients can back off.

7How do you choose the key to limit on?Very often asked

By what you want to protect and who you trust: authenticated user or API key for fairness, IP for anonymous traffic (beware shared NAT and IPv6 ranges), tenant for multi-tenant plans, and endpoint or cost for expensive operations.

8How do you rate-limit by cost instead of request count?Very often asked

Assign weights to operations (a search costs 5, a read 1, or token counts for LLM calls) and subtract the weight from the bucket instead of one. This matches limits to real resource use.

9How do you handle clock differences across servers?Very often asked

Use the central store's clock (for example Redis TIME inside the Lua script) rather than each server's clock, or algorithms that rely on store-side expiry, so skew between app servers does not change limits.

10How do you reduce latency added by a central limiter?Very often asked

Keep the store close (same region), use pipelining or Lua for a single round trip, cache denials briefly locally, or use local token buckets that sync with the central count periodically, accepting slight over-admission.

11How would you design tiered limits for free and paid plans?Very often asked

Store limits per plan in configuration, look up the caller's plan from the API key (cached), apply the matching bucket size and refill rate, and expose current usage in headers and a dashboard so customers can see when they will be limited.

12What is the difference between rate limiting and throttling?Very often asked

Rate limiting rejects requests beyond a limit. Throttling slows them down, for example queueing or delaying requests to smooth bursts. Both protect capacity; throttling suits background or internal traffic where waiting is acceptable.

13How would you rate-limit a GraphQL API where one query can be very expensive?Very often asked

Compute a query cost before execution from depth, list sizes and field weights, reject queries above a maximum cost, and charge the cost against a per-client budget in a token bucket. Return the cost and remaining budget in the response extensions so clients can tune their queries.

14How do you rate-limit WebSocket connections and messages?Very often asked

Limit connection attempts per user and IP at the gateway, cap concurrent connections per account, and apply a token bucket to messages inside each connection. Close or slow abusive connections with a clear close code rather than silently dropping messages.

15What should happen if the limiter's store goes down?Often asked

Usually fail open, with a conservative local in-memory limit per node, so a cache outage does not become an API outage. Sensitive endpoints such as login or OTP can fail closed instead. Either way, alert on it.

16How do you protect login endpoints specifically?Often asked

Limit attempts per account and per IP with escalating delays, add CAPTCHA after several failures, alert on credential-stuffing patterns across many accounts, and avoid revealing whether the account exists.

17How do you test a rate limiter?Often asked

Unit-test the algorithm with a fake clock, load-test with tools like k6 to check limits under concurrency, verify headers and 429 responses, and test behaviour when the store is slow or down.

18How should clients react to 429 responses?Often asked

Read Retry-After, back off exponentially with jitter, avoid retry storms, queue non-urgent work, and surface a clear message to users when they hit a hard limit.

19What is the leaky bucket good for?Often asked

Smoothing output to a constant rate: requests enter a queue that drains at a fixed pace, which suits protecting downstream systems that cannot handle bursts, at the cost of added latency or drops when the queue is full.

20How do fixed windows cause boundary bursts?Often asked

A client can send the full limit at the end of one window and again at the start of the next, doubling the rate briefly. Sliding windows or token buckets smooth this.

21How do you limit concurrent requests rather than rate?Often asked

Use a semaphore or counter of in-flight requests per key, incremented on start and decremented on finish (with a TTL safety net), rejecting new ones above the maximum. This protects slow, expensive endpoints.

22How do you exempt internal or trusted traffic?Often asked

Use allowlists for service accounts or internal networks, separate higher limits for partners, and authenticate internal calls so exemptions cannot be spoofed by headers.

23How do global and per-region limits interact?Often asked

Per-region limits are fast and simple but let a client exceed the global total by spreading across regions. Global limits need cross-region coordination or periodic syncing; many systems accept per-region limits sized as a share of the global one.

24How do you keep a limiter working when Redis is unavailable?Often asked

Decide a failure mode per endpoint: fail open with a generous local in-memory limit for most APIs, fail closed for sensitive ones like login. Use short timeouts and a circuit breaker so the limiter never becomes the outage itself.

25How would you limit outbound calls your service makes to a third-party API?Often asked

Put a shared token bucket in front of the client library sized to the provider's quota, queue or delay calls when tokens run out, respect the provider's Retry-After, and spread the quota across workers through a central store.

26How do you stop one large customer's batch job from starving others?Often asked

Use per-tenant limits plus fair queuing: each tenant gets its own queue or weight, and a scheduler takes work round-robin or by weight, so one tenant's backlog waits behind its own share instead of blocking everyone.

27How do you roll out a new, stricter limit safely?Often asked

Run it in shadow mode first, logging who would have been limited without rejecting. Review the impact, notify affected customers, then enforce it gradually with a feature flag, watching 429 rates and support tickets.

28How do you observe a rate limiter in production?Sometimes asked

Track allowed and rejected counts per key, endpoint and plan, top limited clients, limiter latency and store errors, and alert on sudden spikes in 429s that may indicate attacks or misconfigured limits.

29What is adaptive rate limiting?Sometimes asked

Adjusting limits automatically based on system health, such as lowering limits when latency or error rates rise (load shedding), so the system protects itself during incidents.

30Why might you return 503 instead of 429?Sometimes asked

429 means this client exceeded its limit. 503 means the service as a whole is overloaded or shedding load, regardless of the client's usage.

31How do you document rate limits for API users?Sometimes asked

Publish limits per plan and endpoint, the headers returned, recommended retry behaviour and how to request higher limits, and keep them versioned with the API docs.

32What are the trade-offs of rate-limiting at the CDN or WAF layer?Sometimes asked

Edge limits stop floods before they reach your servers and absorb volumetric attacks cheaply, but they see less context, usually only IP, path and headers, so per-user or per-plan limits still belong in the API gateway or application.

Objective questions 32

1Which HTTP status code signals that a client is being rate-limited?Asked almost every time
  1. A503 Service Unavailable
  2. B409 Conflict
  3. C403 Forbidden
  4. D429 Too Many RequestsCorrect answer

Why: 429 is the standard status, ideally with a Retry-After header saying when to try again.

2Where should rate limiting ideally happen?Asked almost every time
  1. AAfter the business logic
  2. BAt the gateway or edgeCorrect answer
  3. COnly in the database
  4. DIn the browser

Why: Rejected requests should not reach the backend.

3Which header tells a client when to retry?Asked almost every time
  1. ACache-Control
  2. BX-Retry
  3. CExpires
  4. DRetry-AfterCorrect answer

Why: Sent with 429 responses.

4Why use the store's clock rather than each server's?Asked almost every time
  1. AServer clocks can driftCorrect answer
  2. BIt is faster
  3. CIt is required by HTTP
  4. DTo save memory

Why: Skew would change the effective limit.

5Which algorithm allows short bursts while keeping a fixed average rate?Very often asked
  1. ARound robin
  2. BFixed window counter
  3. CToken bucketCorrect answer
  4. DLeaky bucket

Why: Tokens accumulate up to the bucket size, so a burst can spend them, while the refill rate caps the average.

6Which algorithm stores every request timestamp?Very often asked
  1. AToken bucket
  2. BLeaky bucket
  3. CSliding window logCorrect answer
  4. DFixed window counter

Why: Precise but memory-heavy.

7What problem do fixed windows have?Very often asked
  1. AThey need Lua
  2. BThey never reset
  3. CThey are too precise
  4. DBursts at window boundariesCorrect answer

Why: Up to double the limit around the boundary.

8Which key is best for fair limits on an authenticated API?Very often asked
  1. ATime of day
  2. BRequest path only
  3. CUser or API keyCorrect answer
  4. DBrowser type

Why: IPs may be shared by many users.

9Which algorithm smooths output to a constant rate?Very often asked
  1. ALeaky bucketCorrect answer
  2. BFixed window
  3. CSliding log
  4. DRandom drop

Why: Requests drain from a queue at a fixed pace.

10How should LLM API calls be limited?Very often asked
  1. ABy IP only
  2. BThey should not be limited
  3. CBy tokens or cost, not just requestsCorrect answer
  4. DBy request count only

Why: Requests vary hugely in cost.

11What does a concurrency limit restrict?Very often asked
  1. AResponse size
  2. BHeaders
  3. CThe number of in-flight requestsCorrect answer
  4. DRequests per day

Why: Protects slow endpoints.

12How should a GraphQL API limit expensive queries?Very often asked
  1. ACount HTTP requests only
  2. BBlock all nested queries
  3. CLimit by response size after sending
  4. DCharge a computed query cost against a budgetCorrect answer

Why: One GraphQL request can cost far more than another, so cost is the fair unit.

13What is shadow mode for a new limit?Very often asked
  1. ALogging who would be limited without rejectingCorrect answer
  2. BHiding the limit from documentation
  3. CLimiting only at night
  4. DApplying it to internal users only

Why: It shows the real impact before anyone is blocked.

14Why use a Lua script in Redis for the limiter?Often asked
  1. AIt avoids storing keys
  2. BLua is faster than C
  3. CThe check and the update run atomically in one stepCorrect answer
  4. DIt encrypts the counters

Why: Redis runs a script atomically, so no other request can sneak in between reading the count and updating it.

15What should clients add to backoff?Often asked
  1. ANothing
  2. BRandom jitterCorrect answer
  3. CFixed 1 ms waits
  4. DImmediate retries

Why: Avoids synchronised retry storms.

16Which status means the whole service is overloaded?Often asked
  1. A404
  2. B503Correct answer
  3. C429
  4. D401

Why: 429 means one client hit its limit.

17What extra protection suits login endpoints?Often asked
  1. ANo limits
  2. BCaching responses
  3. CPer-account limits and CAPTCHA after failuresCorrect answer
  4. DHigher limits

Why: Defends against brute force.

18Throttling differs from limiting by…Often asked
  1. AIgnoring bursts
  2. BDelaying requests instead of rejectingCorrect answer
  3. CAlways rejecting
  4. DOnly applying to GET

Why: Requests wait rather than fail.

19Which tool load-tests a limiter?Often asked
  1. Ak6Correct answer
  2. BPrettier
  3. CWebpack
  4. DESLint

Why: Generates concurrent traffic.

20What does adaptive limiting respond to?Often asked
  1. ASystem health like latency and errorsCorrect answer
  2. BTime zones
  3. CCode style
  4. DBrowser versions

Why: Sheds load during incidents.

21Per-region limits can let a client…Often asked
  1. ABypass authentication
  2. BUse more memory
  3. CExceed the global total across regionsCorrect answer
  4. DNever send requests

Why: Coordination is needed for strict global limits.

22What reduces limiter latency to one round trip?Often asked
  1. ASynchronous logging
  2. BA Lua script or pipeliningCorrect answer
  3. CMore app servers
  4. DBigger payloads

Why: Read and write happen together.

23If the limiter's store is down, a login endpoint should usually…Often asked
  1. AFail open with no limit
  2. BReturn 200 for everyone
  3. CDisable passwords
  4. DFail closedCorrect answer

Why: Brute-force protection matters more than availability for login.

24What keeps one tenant's backlog from starving others?Often asked
  1. AFair queuing with per-tenant sharesCorrect answer
  2. BA single FIFO queue
  3. CBigger servers only
  4. DDisabling retries

Why: Each tenant waits behind its own work, not everyone's.

25Calls to a third-party API with a 100 per second quota should be…Often asked
  1. ASent as fast as possible
  2. BRetried immediately on 429
  3. CMade from the browser
  4. DShaped by a shared token bucket sized to the quotaCorrect answer

Why: Staying under the provider's quota avoids their 429s and bans.

26What should limit messages inside an open WebSocket?Often asked
  1. AA per-connection token bucketCorrect answer
  2. BThe HTTP 429 status
  3. CDNS TTLs
  4. DThe TLS handshake

Why: Messages arrive on one connection, so the limit lives inside it.

27What should rate-limit dashboards track?Sometimes asked
  1. AOnly CPU
  2. BOnly disk
  3. CNothing
  4. DAllowed and rejected counts per keyCorrect answer

Why: Find abusive or misconfigured clients.

28How should trusted internal traffic be exempted?Sometimes asked
  1. AA spoofable header
  2. BNo authentication
  3. CBy user agent
  4. DAuthenticated service identities or allowlistsCorrect answer

Why: Exemptions must not be forgeable.

29Which headers describe remaining quota?Sometimes asked
  1. AContent-Length
  2. BAccept
  3. CRateLimit-Remaining and RateLimit-ResetCorrect answer
  4. DETag

Why: Standardised rate-limit headers.

30Where should limits per plan be stored?Sometimes asked
  1. AIn the client
  2. BIn DNS
  3. CConfiguration looked up by API keyCorrect answer
  4. DHard-coded in each handler

Why: Easy to change per plan.

31IPv6 limits are often applied to…Sometimes asked
  1. AOnly IPv4
  2. BMAC addresses
  3. CA prefix such as /64Correct answer
  4. DEach full address

Why: One user may hold many IPv6 addresses.

32What can an edge or WAF limiter usually not see?Sometimes asked
  1. AThe user's plan and account identityCorrect answer
  2. BThe client IP
  3. CThe request path
  4. DRequest rate per IP

Why: Per-plan limits need application context the edge lacks.

Track your progress through every blueprint in your dashboard.

Start learning