<!-- Source: https://memory.svelte.page/compare/vs-node-cache -->
<!-- Canonical: https://memory.svelte.page/compare/vs-node-cache -->
# Memory Cache vs node-cache

The Classic TTL Cache vs a Modern TypeScript Rewrite

## Overview

Compare node-cache and @humanspeak/memory-cache: two in-memory TTL caches for Node.js with different answers on LRU eviction, value cloning, TypeScript support, bulk invalidation, and method memoization.

- **Memory Cache site:** https://memory.svelte.page
- **Memory Cache npm:** https://www.npmjs.com/package/%40humanspeak%2Fmemory-cache
- **Memory Cache slug:** memory-cache
- **Category:** In-Memory TTL Cache
- **Approach:** EventEmitter-based key-value store with a periodic expiry sweep (checkperiod)
- **GitHub:** https://github.com/node-cache/node-cache
- **npm:** https://www.npmjs.com/package/node-cache

## Feature comparison

| Feature | @humanspeak/memory-cache | node-cache | Notes |
| --- | --- | --- | --- |
| Zero Dependencies | Yes | No | node-cache depends on clone because it deep-clones values on set and get by default (useClones), which also adds per-operation overhead. |
| TypeScript Support | Written in TypeScript | Bundled typings |  |
| TTL Expiration | Per cache instance | stdTTL + per-key override | node-cache lets ttl(key, ttl) override the default per key. Memory Cache sets one TTL per cache instance — create purpose-scoped caches for different lifetimes. |
| LRU Eviction | Yes | No | When node-cache reaches maxKeys, set() throws ECACHEFULL instead of evicting. Memory Cache evicts the least recently used key after pruning expired entries. |
| Bounded Memory | maxSize with LRU eviction | maxKeys (set() throws when full) |  |
| Wildcard / Prefix Deletion | deleteByMagicString + deleteByPrefix | No |  |
| Method Memoization Decorator | @cached, async-aware | No |  |
| Async Fetch De-Duplication | getOrSet() collapses concurrent lookups | No |  |
| Lifecycle Instrumentation | Six lifecycle hooks | EventEmitter events (set, del, expired, flush) |  |
| Built-In Statistics | Yes | Yes | Both track hits and misses. node-cache adds rough key/value size estimates; Memory Cache adds eviction and expiration counters. |
| Browser Support | Yes | Node-focused |  |
| Active Maintenance | Yes | Dormant (last release v5.1.2, 2020) |  |

## Memory Cache strengths

- Zero runtime dependencies — works in Node and the browser
- TypeScript-first with fully typed generics (MemoryCache<T>)
- TTL expiration and true LRU eviction in one cache — expired entries are pruned before any valid key is evicted
- Wildcard + prefix bulk invalidation (deleteByMagicString, deleteByPrefix)
- @cached decorator for method-level memoization — async-aware with in-flight de-duplication
- getOrSet() async fetch helper that de-duplicates concurrent lookups for the same key
- Lifecycle hooks (onHit, onMiss, onSet, onDelete, onExpire, onEvict) plus built-in getStats()
- Synchronous reads and writes — no await on the hot path

## node-cache strengths

- Battle-tested with a huge install base and years of production use
- Per-key TTL overrides (ttl, getTtl) and take() for read-and-delete
- Value cloning by default isolates cached data from later mutations
- Batch operations (mget, mset) out of the box

## Memory Cache limitations

- Smaller community (newer project)
- In-process only — no persistence or multi-process sharing by design
- TTL is configured per cache instance, not per entry

## node-cache limitations

- No eviction policy — a full cache throws ECACHEFULL instead of making room
- Deep-clones values on every set and get by default, a real cost for large objects
- Dormant maintenance — no substantial release since 2020
- No bulk invalidation, memoization decorator, or TypeScript-native API

## Verdict

node-cache is the incumbent for a reason: it is simple, stable, and everywhere, and its per-key TTL overrides are genuinely handy. But it has been dormant since 2020, clones every value by default, and throws when full instead of evicting. If you want a bounded cache that manages its own memory, typed generics, wildcard invalidation, and a @cached decorator, Memory Cache is the modern replacement. If you only need a tiny TTL map and already depend on node-cache, there is no urgent reason to switch.

## Keywords

node-cache alternative, node-cache vs memory-cache, in-memory cache node.js, ttl cache typescript, lru eviction node-cache, node cache comparison
