s3fifo
v1.0.1
Published
A fast and highly efficient cache for Node.js, implementing the S3-FIFO caching algorithm.
Maintainers
Readme
s3fifo
A fast, zero-dependency, highly efficient in-memory cache for Node.js, implementing the S3-FIFO caching algorithm with full TypeScript support, cold-start persistence (dump/load), and resource lifecycle management (dispose).
S3-FIFO provides significantly higher cache hit rates than LRU, especially in environments where the cache capacity is small relative to the total working set (e.g. database front caches).
Installation
npm install s3fifoQuick Start
import { S3Fifo } from "s3fifo";
const cache = new S3Fifo<string>({ max: 1000 });
cache.set("key1", "value1");
console.log(cache.get("key1")); // 'value1'
console.log(cache.size); // 1
console.log(cache.has("key1")); // true
cache.delete("key1");
cache.clear();Options
When initializing S3Fifo, you can pass the following configuration options (Config<V>):
max(number, required): The maximum number of resident items the cache can hold.ttl(number, optional): The global Time-To-Live in milliseconds.ttlResolution(number, optional): Interval in ms for background timestamp updates (default:100).allowStale(boolean, optional): Iftrue, agetcall returns an expired item before it is removed.noDeletionOnStaleGet(boolean, optional): Iftrue, callinggeton an expired item will not automatically delete it.ttlUpdateAgeOnSet(boolean, optional): Iftrue, callingseton an existing item refreshes its TTL.dispose(function, optional): Callback invoked when an item is evicted, deleted, cleared, or overwritten. Signature:(key: string, value: V, reason: 'evict' | 'set' | 'delete' | 'clear') => void.noDisposeOnSet(boolean, optional): Iftrue, suppresses callingdisposewhen overwriting an existing key viaset(default:false).
API Reference
Core Methods
set(key: string, value: V, ttl?: number): Adds or updates an item in the cache with optional item-specific TTL.get(key: string): Retrieves the value for the given key. Returnsundefinedif missing or expired.peek(key: string): Retrieves the value without updating frequency counters or TTL age (pure side-effect-free view).has(key: string, options?: { includeStale?: boolean }): Returnstrueif key exists and has not expired.delete(key: string): Removes the item associated with the key.clear(): Empties the entire cache.close(): Clears the cache, releases active background interval timers, and marks cache as closed to prevent memory leaks.
Cold-Start Persistence (dump & load)
Prevents Database Thundering Herd / Cache Stampede on server restarts by dumping and pre-warming cache state:
// Dump active entries (preserves creation timestamps & remaining TTL)
const dumpData = cache.dump((key, value) => !key.startsWith("temp:"));
// Save to disk or Redis
fs.writeFileSync("cache-dump.json", JSON.stringify(dumpData));
// On server startup: restore pre-warmed cache
const restoredData = JSON.parse(fs.readFileSync("cache-dump.json", "utf-8"));
cache.load(restoredData);Properties
size: Returns the current number of active resident items in the cache ($O(1)$).max: Returns the maximum configured capacity.isClosed: Returnstrueifclose()has been called.
Iterators (JS Map Style)
keys(): Returns a generator yielding all active resident keys.values(): Returns a generator yielding all active resident values.entries(): Returns a generator yielding all active[key, value]pairs.[Symbol.iterator](): Enables standardfor (const [key, value] of cache)loops.forEach(callback, thisArg?): Executes callback for each active resident entry.
Lifecycle Management (dispose)
const cache = new S3Fifo<Buffer>({
max: 100,
dispose: (key, buffer, reason) => {
console.log(`Item ${key} removed due to ${reason}`);
// Safe resource cleanup (e.g. closing file handles or DB connections)
},
});Note: dispose callbacks are safely deferred to the end of the cache operation to prevent re-entrancy bugs.
Benchmark
Tested using a Zipfian distribution (skew=0.99, pool=100,000 requests) comparing lru-cache to s3fifo:
| Cache Size (% of Pool) | lru-cache (Hit Rate / Throughput) | s3fifo (Hit Rate / Throughput) | | :--------------------: | :-------------------------------: | :----------------------------: | | 1% | 48.9% / 10.8M ops/sec | 58.3% / 15.5M ops/sec | | 5% | 65.0% / 10.8M ops/sec | 71.1% / 14.4M ops/sec | | 10% | 72.3% / 10.2M ops/sec | 76.4% / 14.3M ops/sec | | 25% | 82.1% / 10.3M ops/sec | 82.7% / 13.5M ops/sec | | 50% | 89.0% / 10.3M ops/sec | 86.3% / 14.7M ops/sec |
License
ISC
