FrontendAtlas
Interview Questions
Home>JavaScript interview questions> JavaScript coding challenges >Create an LRU Cache (Bounded Memory)

Create an LRU Cache (Bounded Memory)

hard
By FrontendAtlas Editorial · Updated Feb 5, 2026
Implement createLruCache(maxSize) to keep a bounded, eviction-based cache. This is a classic way to prevent "memory leaks" caused by unbounded Maps in long-lived SPAs (analytics, image metadata, computed results).

Arguments

  • maxSize: number — Maximum number of entries to retain. Must be a positive integer.

Returns

{ get, set, has, size, clear, keys } — An LRU cache API backed by Map insertion order.
Examples
const c = createLruCache(2);
c.set('a', 1);
c.set('b', 2);
c.get('a'); // => 1 (a becomes most-recent)
c.set('c', 3); // evicts b
c.has('b'); // => false

Solution

Overview

In JavaScript, Map preserves insertion order. You can implement LRU by moving a key to the end on get/set, and evicting the first key when size exceeds maxSize.

1

Approach: Map insertion-order (recommended)

Rules:

  • get(key): if present, move to most-recent (delete + set).
  • set(key, value): write, then evict oldest if size > maxSize.

Complexity:

  • get/set/has: O(1) average
  • keys(): O(n)
export default function createLruCache(maxSize) {
  if (!Number.isFinite(maxSize) || maxSize % 1 !== 0 || maxSize <= 0) {
    throw new TypeError('maxSize must be a positive integer');
  }

  const map = new Map();

  const touch = (key, value) => {
    map.delete(key);
    map.set(key, value);
  };

  const evictIfNeeded = () => {
    while (map.size > maxSize) {
      const oldest = map.keys().next().value;
      map.delete(oldest);
    }
  };

  return {
    get(key) {
      if (!map.has(key)) return undefined;
      const value = map.get(key);
      touch(key, value);
      return value;
    },
    set(key, value) {
      touch(key, value);
      evictIfNeeded();
    },
    has(key) {
      return map.has(key);
    },
    size() {
      return map.size;
    },
    clear() {
      map.clear();
    },
    keys() {
      return Array.from(map.keys());
    }
  };
}
export type LruCache<K, V> = {
  get: (key: K) => V | undefined;
  set: (key: K, value: V) => void;
  has: (key: K) => boolean;
  size: () => number;
  clear: () => void;
  keys: () => K[];
};

export default function createLruCache<K, V>(maxSize: number): LruCache<K, V> {
  if (!Number.isFinite(maxSize) || maxSize % 1 !== 0 || maxSize <= 0) {
    throw new TypeError('maxSize must be a positive integer');
  }

  const map = new Map<K, V>();

  const touch = (key: K, value: V) => {
    map.delete(key);
    map.set(key, value);
  };

  const evictIfNeeded = () => {
    while (map.size > maxSize) {
      const oldest = map.keys().next().value as K;
      map.delete(oldest);
    }
  };

  return {
    get(key: K) {
      if (!map.has(key)) return undefined;
      const value = map.get(key) as V;
      touch(key, value);
      return value;
    },
    set(key: K, value: V) {
      touch(key, value);
      evictIfNeeded();
    },
    has(key: K) {
      return map.has(key);
    },
    size() {
      return map.size;
    },
    clear() {
      map.clear();
    },
    keys() {
      return Array.from(map.keys());
    }
  };
}

Notes & Pitfalls

Pitfalls
  • Unbounded caches become real memory problems in long-lived tabs.
  • A cache key strategy matters: if you key by URL with tracking params, you will explode cardinality.
  • LRU helps memory, but eviction can hurt hit-rate; choose maxSize based on real usage.
Edge cases
  • maxSize must be > 0; throw for invalid inputs.
  • Updating an existing key should refresh recency without growing size.
  • get() should also refresh recency.
Techniques
  • Map insertion order as an LRU list.
  • delete+set to move key to most recent.
  • Evict oldest via map.keys().next().value.

Resources

  • MDN – Map

Similar questions

Run With a Performance Budget (Sync or Async)intermediateCleanup Bag (Dispose Subscriptions)easyMeasure Function Duration (Profiling Wrapper)intermediate

Guides

Frontend interview preparation guideGuideFrontend coding interview questions and prep guideBlueprintJavaScript Problems That Actually Show UpBlueprintBuild Great UI in 60 MinutesBlueprint

Preparing for interviews? Use Frontend Coding Challenges first, then move into a concrete Study Plan before targeted Company Prep.

Open frontend interview questionsBrowse JavaScript interview questionsOpen Essential 60Open Machine Coding HubOpen Frontend Coding ChallengesOpen System DesignOpen Interview Prep GuideOpen System Design BlueprintOpen Framework Prep PathsOpen Study PlansOpen JavaScript mastery study planOpen Company PrepOpen JavaScript Framework Prep Guide
↗Incidents hub
← Prev←45 / 88Next →→