mrkeyoor.com_
Wed 23 Sept 00:34 UTC
npmUtilsupdated 22 Sept 2026

lru_map review

lru_map 0.4.1 is a synchronous, count-bounded JavaScript map that evicts the least recently read or written entry. A native `Map` provides key lookup, while a doubly linked list records oldest-to-newest order. `get()` promotes an entry; `find()` and `has()` inspect without changing recency. The package has no TTL, byte budget, async loader, stale-value policy, or built-in disposal callback. Version 0.4.1 is still the npm release from October 2020, and the repository publishes no GitHub releases. The README now recommends copying its source files for minimal use, which transfers maintenance responsibility to your project.

Verdict

lru_map 0.4.1 installed in 0.8 seconds, occupied 1 MB, bundled to 1.3 KB gzipped, and had 0 audit findings in our sandbox. Its count-only cache is fine for stable legacy code, but a new service that needs TTL, async loading, or removal hooks should install lru-cache instead.

We installed it

Lab card: what happened when we installed lru_mapScreenshot of lru_map documentation
Install✓ · 0.8s1 package on disk · 1 MB
ImportESM import works · require() works · CommonJS package
Browser1.3 KBgzipped (3.5 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does lru_map install cleanly?

Yes. In a fresh container with an empty cache, npm install lru_map finished in 0.8s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does lru_map add to a browser bundle?

1.3 KB gzipped (3.5 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does lru_map work with both ESM and CommonJS?

Yes. Both import 'lru_map' and require('lru_map') worked in Node 22 in our run. The package is published as CommonJS.

Does lru_map include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

lru_map or lru-cache: which should you use?

lru-cache: Use it when TTL, stale entries, size calculation, disposal hooks, or an async fetch method belongs in the cache itself. lru_map 0.4.1 installed in 0.8 seconds, occupied 1 MB, bundled to 1.3 KB gzipped, and had 0 audit findings in our sandbox.

When should you not use lru_map?

Cached values need expiration by time, stale-while-revalidate behavior, size calculation, or a total byte limit. lru_map only enforces a maximum number of entries.

API stability4/5The npm API has stayed at version 0.4.1 since October 2020, and its small surface covers construction, set, get, find, has, delete, clear, shift, assignment, iteration, and inspection of oldest and newest entries. That long freeze reduces upgrade churn but does not equal a compatibility promise. Several methods intentionally differ from native Map, and the lack of an exports map leaves module resolution dependent on the legacy main field.
Docs3/5The README explains the linked-list design, recency order, TypeScript setup, constructor forms, every public method, iterator order, JSON conversion, and how to wrap `shift()` for capacity-eviction cleanup. The worked example conflicts with the current implementation by showing `set()` returning an evicted entry, while source and API text say it returns the map. TTL, undefined values, async misses, and the consequences of a zero limit are not covered.
Maintenance2/5npm records 0.4.1 as published on October 22, 2020 and the registry metadata was last modified in 2022. GitHub shows an unarchived repository pushed on February 12, 2025 with 7 open issues and pull requests, but it has no GitHub releases or visible newer package line. The README's recommendation to copy the implementation is honest and practical, yet it also signals that adopters may own future compatibility work.
Ecosystem3/5The npm endpoint counted 5,462,662 downloads in the latest completed week, and GitHub reports 798 stars. CommonJS loading, ESM interop in our Node check, bundled declarations, AMD support, and a Map-shaped API keep it usable in old build systems. The package has no adapter or plugin layer, and current cache features such as TTL, fetch deduplication, disposal, and size accounting live in alternatives rather than its ecosystem.

Use it if

  • You need a tiny in-process cache bounded only by entry count, with synchronous values and ordinary JavaScript keys.
  • Reads should update recency, while a separate `find()` operation must inspect a value without keeping it alive.
  • Oldest-to-newest iteration and manual `shift()` eviction are useful to the calling code.
  • A legacy CommonJS application needs bundled TypeScript declarations and cannot adopt an ESM-only cache package.
Skip it if

Setup reality

We installed lru_map 0.4.1 in a fresh Node 22 Bookworm sandbox. npm finished in 0.8 seconds and left 1 package using 1 MB on disk. The package is 48 KB unpacked, with 0 direct dependencies and 0 peer dependencies. npm audit reported 0 known vulnerabilities. TypeScript declarations are included.

The npm artifact is CommonJS and has no exports map. require() worked in our check, and Node's ESM loader also accepted import. There is no config file, native build, credential, or background process. The minified browser bundle measured 3.5 KB and 1.3 KB gzipped with esbuild, small enough that feature fit matters more than transfer size.

Pick a positive entry limit when constructing the cache. set() returns the cache for chaining and silently evicts through shift() after the count exceeds that limit. get() moves a hit to the newest position, while find() leaves order untouched. Missing entries return undefined, which is indistinguishable from a key deliberately storing undefined unless you check has() first.

Values live only inside the current process and have no automatic expiry. A cache around async work must decide whether to store the pending promise, how to remove rejected promises, and how to avoid duplicate loads. oldest and newest expose entry objects that the README says are invalidated by modification and must not be stored or changed. If you vendor the recommended source, copy lru.d.ts too and accept responsibility for fixes after the six-year-old npm release.

Patterns

Create a three-entry cache create-cache

const { LRUMap } = require('lru_map');

const cache = new LRUMap(3);
cache.set('a', 1).set('b', 2).set('c', 3);

The numeric limit counts entries, not bytes. Adding a fourth distinct key evicts the oldest entry.

Read a value and refresh its recency read-and-promote

const value = cache.get('a');
if (value !== undefined) {
  console.log(value);
}

A successful `get()` moves the entry to newest. Use `has()` when `undefined` is a legitimate cached value.

Inspect a value without keeping it alive peek-without-promoting

const value = cache.find('a');

`find()` returns the value without changing LRU order. That behavior differs from `get()`.

Separate a missing key from an undefined value distinguish-undefined

if (cache.has(key)) {
  return cache.find(key);
}
return loadValue(key);

Both `get()` and `find()` return `undefined` on a miss, so `has()` is required when the cache may store undefined.

Remove the least recently used entry evict-oldest

const evicted = cache.shift();
if (evicted) {
  const [key, value] = evicted;
  console.log({ key, value });
}

`shift()` returns a `[key, value]` pair or undefined. It is also the path used by automatic count eviction.

Wrap automatic capacity eviction observe-capacity-eviction

const originalShift = cache.shift;
cache.shift = function () {
  const entry = originalShift.call(this);
  if (entry) onEvict(entry[0], entry[1]);
  return entry;
};

This sees `shift()` and limit-driven eviction. Direct `delete()` and `clear()` do not pass through the wrapper.

Delete one entry and receive its value delete-key

const removedValue = cache.delete('a');

Unlike native Map.delete, this method returns the removed value or undefined, not a success boolean.

Iterate from oldest to newest iterate-by-recency

for (const [key, value] of cache) {
  console.log(key, value);
}

Iteration follows current LRU order. Calling `get()` before iteration can move an entry to the end.

Build a cache from ordered entries seed-from-entries

const cache = new LRUMap(2, [
  ['older', 1],
  ['newer', 2],
]);

Input order becomes oldest to newest. Supplying more entries than the explicit limit makes `assign()` throw an overflow error.

Set capacity from the initial iterable derive-limit-from-input

const cache = new LRUMap([
  ['a', 1],
  ['b', 2],
]);

console.log(cache.limit); // 2

The iterable-only constructor fixes the limit to the number of seeded entries after assignment.

Serialize entries in LRU order serialize-order

const payload = JSON.stringify(cache);
// [{"key":"older","value":1},{"key":"newer","value":2}]

`toJSON()` emits objects with `key` and `value` properties, not the array-of-pairs format accepted by the constructor.

Store one pending promise per key cache-async-work

async function cachedLoad(key) {
  if (cache.has(key)) return cache.get(key);
  const pending = loadValue(key);
  cache.set(key, pending);
  try {
    return await pending;
  } catch (error) {
    if (cache.find(key) === pending) cache.delete(key);
    throw error;
  }
}

lru_map has no async fetch policy. Removing a rejected promise prevents a permanent cached failure, though capacity eviction can still allow duplicate in-flight work.

Alternatives

PackageRegistryPick it when
lru-cachenpmUse it when TTL, stale entries, size calculation, disposal hooks, or an async fetch method belongs in the cache itself.
quick-lrunpmUse it for a small modern ESM cache with maxAge support and a simpler high-level API.
tiny-lrunpmUse it when a compact current package with entry expiry is preferable to lru_map's Map-like surface.
mnemonistnpmUse it when LRU caching is one of several specialized data structures the application needs.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.