Review an Asynchronous Cache for Races, Memory Growth, and Thread Safety

Read the full interview experience this question came from →

Quick Overview

Review JavaScript cache defects, shared in-flight loads, invalidation races, eviction, garbage collection, and the C++ multithreaded synchronization contrast.

Review an Asynchronous Cache for Races, Memory Growth, and Thread Safety

Company: Mercor

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: hard

Interview Round: Technical Screen

Review this JavaScript cache sketch. Identify its immediate defects, explain the concurrency problem around an asynchronous load, and describe how you would bound its memory use. Then contrast the synchronization requirements with a shared cache accessed by multiple C++ threads. ```javascript const cache = new Map() function retrieve(key, val) { if (cache.has(key)) { return cache.get(key) } const newVal = await longRunningFn(key) cache.set(key) return newVal } ``` ### Part 1 — Correctness and Asynchronous Interleaving Explain the syntax/API issues and what happens when two calls miss the same key before either load completes. Propose a policy for sharing in-flight work and handling failed or outdated loads. #### What This Part Should Cover The missing async declaration, missing stored value, unused parameter, duplicate work, promise/result contracts, and invalidation races. ### Part 2 — Memory and Eviction Explain why garbage collection does not automatically make this cache bounded. Discuss a capacity or expiration policy and how it interacts with in-flight loads. #### What This Part Should Cover Reachability, eviction, failure cleanup, value size, and observable cache behavior. ### Part 3 — Multithreaded Access Explain what changes for a C++ map shared by several threads and where synchronization belongs. #### What This Part Should Cover Physical data-race protection, compound check/claim operations, shared in-flight state, and avoiding a global lock around slow I/O. ### Constraints For the JavaScript baseline, use one event loop without shared-memory workers. That assumption does not rule out asynchronous interleaving. For the C++ contrast, assume genuine concurrent access to shared state. The required freshness and eviction policies remain design choices to declare. ### Clarifying Questions - Should concurrent requests for one key share a load, and should failed loads be cached? - Can callers invalidate or overwrite an entry while a load is running? - Is the memory limit based on entry count or estimated bytes? ```hint Separate language threads from logical races Two JavaScript calls can interleave across await even when their synchronous instructions do not execute simultaneously. ``` ### What a Strong Answer Covers - Immediate code defects and a consistent asynchronous return contract. - Per-key coordination, stale-completion protection, and bounded retention. - Correct distinctions between event-loop interleaving, C++ locking, and garbage collection. ### Follow-up Questions - How would you prevent an older load from replacing a newer explicit write? - How would you evict a value without causing every waiter to start another load?

Overview: Review JavaScript cache defects, shared in-flight loads, invalidation races, eviction, garbage collection, and the C++ multithreaded synchronization contrast.

Read the full Mercor Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Mercor
Mercor logo
Mercor
Sep 3, 2026
hardSoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
1
0

Review this JavaScript cache sketch. Identify its immediate defects, explain the concurrency problem around an asynchronous load, and describe how you would bound its memory use. Then contrast the synchronization requirements with a shared cache accessed by multiple C++ threads.

const cache = new Map()
function retrieve(key, val) {
  if (cache.has(key)) {
    return cache.get(key)
  }
  const newVal = await longRunningFn(key)
  cache.set(key)
  return newVal
}

Part 1 — Correctness and Asynchronous Interleaving

Explain the syntax/API issues and what happens when two calls miss the same key before either load completes. Propose a policy for sharing in-flight work and handling failed or outdated loads.

What This Part Should Cover Guidance

The missing async declaration, missing stored value, unused parameter, duplicate work, promise/result contracts, and invalidation races.

Part 2 — Memory and Eviction

Explain why garbage collection does not automatically make this cache bounded. Discuss a capacity or expiration policy and how it interacts with in-flight loads.

What This Part Should Cover Guidance

Reachability, eviction, failure cleanup, value size, and observable cache behavior.

Part 3 — Multithreaded Access

Explain what changes for a C++ map shared by several threads and where synchronization belongs.

What This Part Should Cover Guidance

Physical data-race protection, compound check/claim operations, shared in-flight state, and avoiding a global lock around slow I/O.

Constraints

For the JavaScript baseline, use one event loop without shared-memory workers. That assumption does not rule out asynchronous interleaving. For the C++ contrast, assume genuine concurrent access to shared state. The required freshness and eviction policies remain design choices to declare.

Clarifying Questions Guidance

  • Should concurrent requests for one key share a load, and should failed loads be cached?
  • Can callers invalidate or overwrite an entry while a load is running?
  • Is the memory limit based on entry count or estimated bytes?

What a Strong Answer Covers Guidance

  • Immediate code defects and a consistent asynchronous return contract.
  • Per-key coordination, stale-completion protection, and bounded retention.
  • Correct distinctions between event-loop interleaving, C++ locking, and garbage collection.

Follow-up Questions Guidance

  • How would you prevent an older load from replacing a newer explicit write?
  • How would you evict a value without causing every waiter to start another load?
Loading comments...