Introduction
@warlock.js/cache is a standalone Node.js caching library. It turns slow, repeated work — database queries, API calls, heavy computations — into cheap memory reads.
// Before: every request hits the database (~50ms each)app.get("/product/:id", async (req, res) => { const product = await db.products.findById(req.params.id); res.json(product);});
// After: the first request hits the database, the next 999 don't (~1ms each)app.get("/product/:id", async (req, res) => { const product = await cache.remember( `products.${req.params.id}`, "1h", () => db.products.findById(req.params.id), ); res.json(product);});What’s in the box:
- 8 interchangeable drivers — Redis, Memory, Memory Extended, LRU, File, Null, Postgres (with optional pgvector), and Mock for tests.
- Rich
setoptions —ttl/expiresAt/tags/onConflict/ per-calldriver/vectorfor similarity. - Atomic operations —
increment,decrement,update,merge, conditional writes. - Cache tags — group related entries and invalidate them together.
- List sub-API — queues, stacks, recent-N buffers.
- Similarity retrieval — store embeddings alongside entries, query by meaning (what’s similarity?).
- Stampede prevention — when 1000 concurrent requests all miss the same key, only one hits the source of truth (what’s a stampede?).
- Stale-while-revalidate — return cached data instantly while a background refresh runs, so slow upstreams never make fast endpoints slow (SWR guide).
- Event system — observe every cache operation.
- Built-in metrics —
cache.metrics()returns hit rate, latency percentiles, per-driver breakdowns (metrics guide).
:::info Standalone Package Works independently of the Warlock framework in any Node.js environment — Express, Fastify, NestJS, Next.js, Remix, or any other runtime that runs on Node.js. :::
:::tip TypeScript or JavaScript
Examples use TypeScript. If you’re on plain JS, just drop the <Type> generics — everything works identically at runtime.
:::
Installation
Section titled “Installation”npm install @warlock.js/cacheyarn add @warlock.js/cachepnpm add @warlock.js/cacheCore Operations
Section titled “Core Operations”| Method | Description |
|---|---|
set(key, value, ttlOrOptions?) | Store a value with optional TTL or rich options |
get(key) | Retrieve a cached value |
remove(key) | Delete a cache entry |
has(key) | Check if a key exists |
pull(key) | Get a value and delete it |
forever(key, value) | Store a value without expiration |
remember(key, ttl, callback) | Get cached value or compute and cache it (with stampede prevention) |
flush() | Clear all cache entries |
increment(key, amount) | Atomically increment a numeric value |
decrement(key, amount) | Atomically decrement a numeric value |
update(key, fn) | Atomic read-modify-write for objects |
merge(key, partial) | Shallow-merge a partial into a cached object |
list<T>(key) | Typed list accessor (push/shift/slice/trim) |
many(keys) | Retrieve multiple values at once |
setMany(entries, ttl?) | Store multiple values at once |
removeNamespace(namespace) | Delete all keys matching a namespace pattern |
Conditional writes — “set only if missing” or “set only if present” — are expressed via set(k, v, { onConflict: "create" \| "update" }) and work across every driver (Redis-native, others emulated).
Drivers
Section titled “Drivers”| Use Case | Recommended Driver |
|---|---|
| Production, multi-server, distributed | Redis |
| Local development, simple persistence | File |
| Fastest, ephemeral, single-process | Memory |
| Need sliding expiration | Memory Extended |
| Limited memory, want LRU eviction | LRU Memory |
| Testing, disable cache | Null |
Advanced Features
Section titled “Advanced Features”- Set Options — rich third-arg object:
ttl,expiresAt,tags,onConflict, per-calldriver - Update & Merge — atomic read-modify-write for structured values
- Cache Lists — queue / stack / recent-N buffer sub-API
- Cache Tags — group related entries and invalidate them together
- Atomic Operations — increment, decrement, and conditional writes without race conditions
- Stampede Prevention —
remember()shares one concurrent regeneration per key - Events — observe every cache operation with 9 event types
- Errors — error classes and how to react
Quick Example
Section titled “Quick Example”import { cache, RedisCacheDriver } from "@warlock.js/cache";
cache.setCacheConfigurations({ default: "redis", drivers: { redis: RedisCacheDriver }, options: { redis: { url: process.env.REDIS_URL, globalPrefix: "shop" } },});await cache.init();
// Cache a product for 1 hour (human-readable duration string)const product = await cache.remember( `products.${productId}`, "1h", () => db.products.findById(productId),);
// Invalidate all cached orders for a user after checkoutawait cache.removeNamespace(`orders.${userId}`);