FrontendPro

51Implement a token-bucket API rate limiter

mediumAbout 35 minutesCodingrate-limitingalgorithmstimers

Problem

A token bucket holds up to capacity tokens and refills continuously at refillPerSecond tokens per second. Every request spends tokens; a request without enough tokens must wait. This allows short bursts (up to capacity) while keeping the long-run rate at refillPerSecond.

Implement createTokenBucket({ capacity, refillPerSecond, now = Date.now }) returning:

  • tryRemove(count = 1): spend count tokens and return true if there are enough, otherwise return false and spend nothing.
  • tokens(): the current number of tokens (may be fractional).
  • msUntil(count = 1): how many milliseconds until count tokens will be available (0 if they already are).
  • take(count = 1): an async version that waits until the tokens are available, then spends them.

The bucket starts full. now is injectable so time can be controlled in tests.

const limiter = createTokenBucket({ capacity: 10, refillPerSecond: 5 });

async function callApi(path) {
  await limiter.take(); // at most 10 at once, then 5 per second
  return fetch(path);
}

Requirements

  • Do not use a timer to refill; compute the refill from the elapsed time when you need it.
  • Never exceed capacity.
  • tryRemove with count > capacity always returns false, and take rejects with a RangeError for it, because it could never succeed.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

solution.jsJavaScript

Press Run or ⌘ Enter to execute your code.

Step-by-step

Keep tokens (start at capacity) and last = now().

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 2 code listings, 4 edge cases, 5 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever