npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lazy-layers-cache

v0.6.3

Published

A TypeScript hybrid L1/L2 cache with lazy loading, inflight dedupe, event-bus invalidation, cross-instance L1 priming, and a live observability dashboard with Prometheus + OpenTelemetry.

Readme

lazy-layers-cache

L1/L2 caching for Node.js services and Cloudflare Workers. Use Redis or Cloudflare KV as shared L2, with getOrSet and pattern invalidation in Hono or other frameworks.

npm version CI license types

Docs · Memory and cost calculator · LLM index · Full LLM context

Get started

Requires Node.js 20 or 22+. Use Node.js 22+ for the NATS integration because its current transitive dependency declares that minimum. Redis is optional for a single process.

npm install lazy-layers-cache

Save this as cache-demo.mjs and run node cache-demo.mjs:

import { setupCache } from 'lazy-layers-cache'

const cache = await setupCache({ namespace: 'demo', redis: false })
let loaderCalls = 0

try {
  const loadUser = async () => {
    loaderCalls++
    return { id: '42', name: 'Ada' }
  }

  await cache.getOrSet('user:42', loadUser)
  const user = await cache.getOrSet('user:42', loadUser)
  console.log(user.name, loaderCalls) // Ada 1
} finally {
  await cache.close()
}

For multiple instances, set REDIS_URL and use:

const cache = await setupCache({
  namespace: 'users-api',
  redis: { required: true },
})

setupCache creates Redis L2 and Redis Pub/Sub, checks readiness, and manages shutdown. Each instance keeps its own L1. Use the same namespace and Redis service for instances that share cached data.

The quickstart takes you from this example to database reads, invalidation, and shutdown.

Cloudflare KV

Use the Workers Hono example with the Worker-safe lazy-layers-cache/cloudflare import and a KV binding. Use the Node.js Hono example with CloudflareKVRestNamespace and setupCache({ kv: { namespace } }). Both support getOrSet and invalidateByPattern with the same key pattern syntax. An optional Cloudflare Queue consumer retries application invalidations from either runtime. The Cloudflare KV guide covers setup, TTLs, and KV limits.

KV writes call serializeCacheValue from lazy-layers-cache or lazy-layers-cache/cloudflare. That facade applies the shared HC1 MessagePack policy with adaptive gzip: payloads at least 1 KiB are compressed only when gzip saves at least 15% of the packed bytes. Set compression: 'none' in a KV store to skip the trial. Compression saves stored bytes, while per-key KV read/write/list/delete charges remain unchanged. Local L1 hits can avoid some KV reads. See the guide for the full cost model and consistency limits.

Cloudflare Event Subscriptions report build and KV namespace lifecycle events to their own platform-monitoring Queue consumer. They do not report individual cache key changes. Application invalidations use the separate invalidation Queue consumer.

The methods you need

| Task | Method | Details | | --- | --- | --- | | Read a value, loading it on a miss | getOrSet(key, loader) | Read API | | Refresh after a committed database write | invalidate(key) | Invalidation | | Invalidate a key family | invalidateByPattern('tenant:42:*') | Pattern API | | Warm a key before traffic needs it | prewarm(key, loader) | Warm-up API | | Release managed resources | close() | Shutdown |

Commit database writes before invalidating. Keep cache loaders read-only. A cache lease reduces duplicate loads but does not authorize a business operation or guarantee exactly-once execution.

What happens on a read

  1. getOrSet returns a cached value from L1 or shared Redis L2 when available.
  2. On a miss, in-flight dedupe shares work within the process. Redis per-key leases coordinate loaders across instances.
  3. A successful load fills the cache when its publication guard remains valid. Scoped event hints can warm peer L1 caches; shared-L2 peers verify current data before promotion.
  4. Redis or bus failures degrade the cache path. Eligible stale data can cover a loader failure, but loader errors, overload, or lock deadlines can still reach the caller.

Built-in L1 retains encoded values with LRU eviction, entry limits, and a shared memory budget. setupCache defaults to a 10 second L1 TTL and a 32 KiB peer-broadcast ceiling. Values above that ceiling skip peer priming. L1 admission can also decline a value under memory pressure.

Use production setup for deployment decisions and configuration for defaults and tuning. Redis Pub/Sub, RabbitMQ, NATS Core, and NATS JetStream have different delivery guarantees.

Latest release: v0.6.3

This update adds bounded followers and internal decoding, scoped invalidation, safer Redis publication during outages, and fixes for binary ownership, TTL propagation and shutdown. L1 expiry checks and event enqueue accounting avoid full-cache or full-queue work on each request.

The isolated Docker suite passes 480 tests on Node 20, 22 and 24, and all 15 fault scenarios pass. Paired measurements show 97.56% lower heap-plus-external retention for 20 empty caches and 99.83% faster expiry checks at 8,192 entries. Warm-read microbenchmarks are 30.46% slower, and the performance gate remains red. These results apply to the documented workloads; outstanding production gates remain visible.

Read the changelog, before/after comparison, migration notes, and production-readiness report. Public API signatures and production dependencies remain unchanged. Install this release with npm install [email protected].

Previous release: v0.5.3

0.5.3 introduced:

  • Transaction coordination: the opt-in lazy-layers-cache/transactions API coordinates attempts around a durable operation using a Redis primary. It stays separate from the cache. Your database, provider idempotency, and reconciliation determine the business result.
  • Lease-checked Redis publication: the store checks ownership and writes the value with its TTL in one Redis operation. A rejected lease cannot publish a successful cache fill.
  • Independent L1/L2 codecs: choose the write representation per layer while continuing to read supported tagged HC1 values.
  • Redis-native retention: native TTL and operator-managed eviction are the default. The namespace index is optional.
  • Read-only capability discovery: bounded checks distinguish supported, unavailable, and unknown capabilities without changing Redis configuration.

When upgrading an existing Redis deployment, review the key-layout migration. v2 and legacy keys are not dual-read. Keep useIndex: true while migrating a deployment that relies on the namespace catalogue.

Read the 0.5.3 changelog for the full release and compatibility notes. For operation coordination, start with the transaction reference and runnable ticketing example.

Find the next answer

| You want to… | Read | | --- | --- | | Add caching to an application | Quickstart | | Follow one key through the system | Walkthrough | | Choose a deployment setup | Production setup | | Handle timeouts and outages | Failure handling | | Inspect cache behavior | Observability | | Look up a method or option | API · Configuration |

Development

npm ci
npm run ci
npm run docs:build

npm run ci builds and checks the ESM/CommonJS package and runs the test suite. See the benchmark guide for reproducible performance and memory workloads, and the examples for runnable integrations.

The cache engineering audit includes isolated Docker correctness/load/fault scripts, source-backed findings, raw before/after measurements, and explicit release gates. Review its compatibility and rollout notes before adopting the audited changes.

License

MIT