Backend DevelopmentHardCodeSystem design

Token Bucket Bouncer

Simulate an API rate limiter that combines a token bucket (for bursts) with a per-minute quota, tracking every client separately.

250 ptsEstimated time: 45 min

Statement

Story

A public API is being hammered by scrapers. The team decides on two limits that work together: a token bucket lets a client burst a little but forces a steady average, and a per-minute quota caps the total regardless of how smooth the traffic looks. Before putting it in front of production you simulate it on recorded traffic and print which requests it would have let through.

The rules

Every client (the string identifying it) has its own state, created at its first request.

  • Token bucket. The bucket holds at most capacity tokens and starts full at the client's first request. It refills continuously at refill tokens per second (so refill = 2 adds one token every 500 ms, and fractions of a token accumulate), never above capacity. A request needs at least one whole token.
  • Fixed-window quota. Time is cut into 60-second windows aligned to time 0: the window of a timestamp t (milliseconds) is floor(t / 60000). A client may have at most window_limit allowed requests in each window; a new window starts counting from zero.
  • A request is allowed only if the bucket has a token and the quota is not used up. Allowed requests take one token and one unit of quota. A denied request takes nothing from either.

The requests arrive in non-decreasing timestamp order across all clients. capacity, refill and window_limit are integers (0 or more), timestamps are integer milliseconds.

Your task

Implement rate_limit(capacity, refill, window_limit, requests) in Python or rateLimit(capacity, refill, windowLimit, requests) in JavaScript. requests is a list of [client, timestamp_ms] pairs. Return a list of booleans, one per request, in order: True when it is allowed.

A test driver calls your function and prints A for every allowed and D for every denied request. Write only the function (and helpers); do not read input or print anything yourself.

Example

capacity = 2, refill = 1, window_limit = 10
requests = [["a", 0], ["a", 0], ["a", 0], ["a", 1000], ["a", 1500], ["b", 1500]]
result   = [True, True, False, True, False, True]    # printed as AADADA

Client a empties its two tokens at time 0, so the third request is denied. One second later exactly one token is back (allowed), but 500 ms later only half a token is (denied). Client b starts with its own full bucket.

Sample input

[{"capacity":2,"refill":1,"window_limit":10,"requests":[["a",0],["a",0],["a",0],["a",1000],["a",1500],["b",1500]]}]

Allowed languages: python, javascript

Hints

Stuck? Hints are optional, and each one lowers the points you earn for solving this challenge.

  1. Hint 1Costs 20 points

    Sign in to reveal hints.

  2. Hint 2Costs 30 points

    Reveal the previous hint first

  3. Hint 3Costs 40 points

    Reveal the previous hint first

Lessons that teach this

Stuck on the ideas rather than the puzzle? These lessons cover what you need.