FrontendPro

107Implement a distributed-style API client rate limiter coordinating multiple browser tabs

hardAbout 60 minutesCodingrate-limitingmulti-tabweb-locksrace-conditions

Problem

A third-party API allows 10 requests per minute per user. Your app may be open in five tabs, and each tab's own limiter thinks it has the full budget. Build a limiter whose budget is shared across tabs.

Implement createSharedRateLimiter({ name, limit, windowMs, storage, lock, now = Date.now, sleep }) returning:

  • tryAcquire(): Promise<boolean>; take a slot if fewer than limit requests were made by any tab in the last windowMs.
  • retryAfter(): Promise<number>; milliseconds until a slot frees (0 if one is free).
  • acquire({ signal } = {}): wait (using sleep(ms)) until a slot is free, then take it; reject with signal.reason if aborted.

Shared pieces are injected so the limiter works in browsers and in tests:

  • storage: async get(key) and set(key, value) (for example a thin wrapper over localStorage or IndexedDB). Keep the request timestamps as a JSON array under "ratelimit:{name}".
  • lock(name, callback): runs callback exclusively, like the Web Locks API (navigator.locks.request(name, callback)), and returns its result.

Requirement: every read-modify-write of the shared state must happen inside the lock. Without it, two tabs can read the same state at the same time and both take the last slot.

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

Every tab reads and writes the same key, "ratelimit:{name}", holding the timestamps of recent requests from all tabs. Storage is the "server" all tabs agree on.

Unlock the full solution

What's inside

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

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

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

All 150 answersOne payment, yours forever