mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmDataupdated 22 Sept 2026

cache-manager review

Our cache-manager 7.2.9 install took 1.9 seconds and produced a 2 MB Node package tree with six packages. The library puts one async API over a default process-memory cache or an ordered list of Keyv stores, then adds bulk reads, expiration, events, function wrapping, request coalescing, and background refresh. Version 7 changed a miss from null to undefined. The current 7.2.9 patch changes its build toolchain, so application behavior is the same as earlier 7.2 releases. This belongs in a Node service; our esbuild browser build failed on Node-only code.

Verdict

cache-manager 7.2.9 installed in 1.9 seconds and used 2 MB in our sandbox, but its browser build failed, so it fits Node services that need Keyv-backed tiers and wrap. Install it only after deciding bounds, TTLs, invalidation, and whether nonBlocking's weaker completion guarantees are acceptable.

We installed it

Lab card: what happened when we installed cache-managerScreenshot of cache-manager documentation
Install✓ · 1.9s6 packages on disk · 2 MB
ImportESM import works · require() works · ESM package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does cache-manager install cleanly?

Yes. In a fresh container with an empty cache, npm install cache-manager finished in 2 seconds, leaving 6 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

Can cache-manager run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does cache-manager work with both ESM and CommonJS?

Yes. Both import 'cache-manager' and require('cache-manager') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does cache-manager include TypeScript types?

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

cache-manager or cacheable: which should you use?

cacheable: Choose it for this monorepo's newer primary and secondary cache model, tag invalidation, and per-store TTLs. cache-manager 7.2.9 installed in 1.9 seconds and used 2 MB in our sandbox, but its browser build failed, so it fits Node services that need Keyv-backed tiers and wrap.

When should you not use cache-manager?

You need a browser cache: our browser bundle failed because esbuild encountered Node-only code

API stability3/5Version 7 has one documented break from version 6: cache misses now return undefined instead of null. The larger adapter break happened in version 6, when Keyv replaced the older store interface. The callable surface in 7.2.9 is compact and typed, but two recent majors affected common read paths and storage configuration, and several README examples still describe the old null result.
Docs3/5The cache-manager README covers installation, Keyv adapters, tier order, every public method, events, refresh behavior, serialization, and migrations from versions 5 and 6. It also contains contradictions that matter in production: examples still show null misses in a version that returns undefined, ttl wording is vague about the absolute timestamp, and some documented event payloads lag the source types.
Maintenance5/5cache-manager 7.2.9 was released on May 27, 2026, and its monorepo was pushed on August 25, 2026. The latest package release moved builds to tsdown and pnpm 11 without advertising runtime changes. GitHub's combined counter currently shows 3 open issues and pull requests, while the source has tests and separate import and require exports. Those repo figures include sibling packages in the cacheable monorepo.
Ecosystem5/5npm recorded 4,427,259 downloads in the latest week, and the cacheable monorepo has 2,005 GitHub stars. The package builds on Keyv, whose adapters cover Redis, Memcache, MongoDB, SQLite, Postgres, MySQL, and etcd. NestJS is a named consumer. That reach is useful, though each adapter brings its own credentials, serialization, network behavior, and shutdown requirements.

Use it if

  • A Node service needs the same get, set, delete, and wrap calls for memory now and a Keyv remote store later
  • You need an in-process L1 cache ahead of Redis or another Keyv store, with earlier stores checked first
  • Several callers in one process may request the same expensive value and wrap should coalesce that work
  • You can define cache keys, TTLs, invalidation, and failure policy instead of expecting the package to choose them
Skip it if

Setup reality

We installed cache-manager 7.2.9 in 1.9 seconds. The fresh Node 22 sandbox ended with six packages using 2 MB on disk. The package itself has two direct dependencies, no peer dependencies, bundled TypeScript declarations, and a 68 KB unpacked size. npm audit reported 0 known vulnerabilities. Both require() and ESM import worked through the exports map.

createCache() needs no credentials because it starts with an in-memory Keyv store. Redis, Postgres, MongoDB, SQLite, and other remote choices require a separate Keyv adapter, its connection details, and a shutdown path that awaits disconnect(). Store order is priority order. TTL arguments are milliseconds, while ttl(key) returns an absolute expiration timestamp.

The default memory store lives in one process and has no configured size bound. Use a bounded adapter when keys can grow without limit. External Keyv instances also bring serialization rules. The README warns that JSON serialization can change Symbol and Uint8Array values, so binary or unusual values need a suitable serializer or serialization disabled. Version 7 returns undefined for an absent or expired key even though stale README examples still show null.

Layered mode is sequential by default. nonBlocking races reads, which lets a quick undefined from one store beat a slower hit, and it returns from mutations before every store settles. wrap prevents duplicate work only within one process. refreshThreshold serves the cached value and starts refresh in the background when its remaining TTL crosses the threshold; entries without a TTL cannot enter that path. Our browser build failed, so keep cache-manager in Node runtime code.

Patterns

Start a process-memory cache create-memory-cache

import { createCache } from 'cache-manager';

const cache = createCache({ ttl: 60_000 });

The default store is confined to one process and has no configured item limit; use a bounded store for high-cardinality keys.

Store a typed value and handle a miss read-write-value

type User = { id: string; name: string };

await cache.set<User>('user:42', { id: '42', name: 'Ada' }, 30_000);
const user = await cache.get<User>('user:42');
if (user === undefined) console.log('miss');

Version 7 returns undefined for a missing or expired key, and the 30_000 TTL is measured in milliseconds.

Use bulk cache operations read-write-many

await cache.mset([
  { key: 'flag:a', value: true },
  { key: 'flag:b', value: false, ttl: 5_000 },
]);
const values = await cache.mget<boolean>(['flag:a', 'flag:b', 'flag:none']);

mget keeps the requested key order and places undefined in each missing position.

Remove selected entries invalidate-values

await cache.del('user:42');
await cache.mdel(['flag:a', 'flag:b']);

del and mdel operate on every configured store; nonBlocking mode returns before all of those deletions settle.

Flush the complete cache clear-all-stores

await cache.clear();

clear() flushes every configured store, so it is unsafe as tenant-specific invalidation unless each tenant has an isolated cache instance.

Cache and coalesce one loader wrap-expensive-call

const user = await cache.wrap(
  'user:42',
  () => database.users.findById('42'),
  60_000,
);

wrap coalesces concurrent work for the same cache ID and key inside this process; a second replica can still run the loader.

Calculate TTL from the loaded value choose-value-ttl

const session = await cache.wrap('session:abc', loadSession, {
  ttl: (value) => value.premium ? 60_000 : 10_000,
});

The TTL callback receives the computed value and must return milliseconds.

Refresh shortly before expiry refresh-hot-entry

const cache = createCache({
  ttl: 60_000,
  refreshThreshold: 10_000,
});
const catalog = await cache.wrap('catalog:v4', loadCatalog);

With less than 10_000 ms remaining, wrap returns the cached value and starts a background refresh; no TTL means no refresh trigger.

Read the absolute expiry time inspect-expiration

await cache.set('rates:usd', rates, 30_000);
const expiresAt = await cache.ttl('rates:usd');
if (expiresAt) console.log(new Date(expiresAt));

ttl() returns an absolute millisecond timestamp from Keyv, not the duration left.

Put bounded memory ahead of Redis configure-memory-redis-tiers

import { createCache } from 'cache-manager';
import { Keyv } from 'keyv';
import KeyvRedis from '@keyv/redis';
import { CacheableMemory } from 'cacheable';

const cache = createCache({ stores: [
  new Keyv({ store: new CacheableMemory({ ttl: 60_000, lruSize: 5_000 }) }),
  new Keyv({ store: new KeyvRedis(process.env.REDIS_URL) }),
] });

The first store has highest read priority; Redis adds credentials, serialization choices, network errors, and a disconnect step.

Turn off JSON serialization for bytes preserve-binary-values

import { Keyv } from 'keyv';

const store = new Keyv();
store.serialize = undefined;
store.deserialize = undefined;
const binaryCache = createCache({ stores: [store] });

Keyv JSON serialization can change Uint8Array and Symbol values; the built-in cache-manager memory store already disables it.

Disconnect adapters during shutdown close-remote-stores

process.once('SIGTERM', () => {
  void cache.disconnect().then(() => {
    process.exitCode = 0;
  });
});

disconnect() closes configured stores that expose a disconnect method, including adapters that keep network sockets open.

Alternatives

PackageRegistryPick it when
cacheablenpmChoose it for this monorepo's newer primary and secondary cache model, tag invalidation, and per-store TTLs.
keyvnpmChoose it when one storage-neutral key-value API is enough and you do not need cache-manager wrap or tier orchestration.
lru-cachenpmChoose it for a bounded cache inside one process with explicit eviction and no remote backend.
@keyv/redisnpmChoose it when direct Keyv-to-Redis access is clearer than adding a second cache facade.

More data guides

numpy · fsspec · pandas · sqlalchemy · pyarrow · lxml · 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.