FrontendPro

54Implement a concurrency-safe async cache with TTL

mediumAbout 35 minutesCodingcachingpromisesrace-conditions

Problem

Implement createAsyncCache({ load, ttl, now = Date.now }). load(key) is an async function that fetches a value. The cache:

  • get(key): returns a promise for the value. A value younger than ttl ms is served from the cache. Otherwise load(key) is called, once, even if many get(key) calls arrive while it is loading.
  • set(key, value): store a value directly (for example after a mutation).
  • delete(key) and clear(): remove entries.
const users = createAsyncCache({ ttl: 30_000, load: (id) => api.getUser(id) });
await users.get(7); // network
await users.get(7); // cache
users.set(7, updatedUser); // after a successful edit

Requirements

  • Concurrent get calls for the same key share one load.
  • Failed loads are not cached: the next get tries again.
  • Race safety: if set, delete or clear happens while a load is in flight, the result of that older load must not overwrite the newer state.
  • now is injectable so tests can control time.

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

values holds { value, expiresAt } for loaded entries. loading holds the in-flight promise per key, so concurrent callers share it.

Unlock the full solution

What's inside

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

Includes 2 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