DEV Community

날다람쥐
날다람쥐

Posted on

Layercache 2.0.0: Millisecond TTLs, Stale-Preserving Expiration, and Better Redis Coverage

Layercache 2.0.0 is out.

This release is intentionally a major version because it changes the public TTL semantics from seconds to milliseconds. That is a breaking change, but it also makes Layercache much more consistent with Node.js timers, Redis PX / PTTL, and most JavaScript runtime APIs.

What changed?

Breaking: TTL values are now milliseconds

Before 2.0.0, TTL examples and parts of the public API used seconds.

In 2.0.0, TTL-related values are consistently milliseconds:

const cache = new CacheStack({
  layers: [memory, redis],
  ttl: 60_000
})

await cache.set("user:1", user, {
  ttl: 30_000,
  staleWhileRevalidate: 120_000,
  staleIfError: 300_000
})
Enter fullscreen mode Exit fullscreen mode

This applies to:

  • layer defaults
  • operation-level ttl
  • negativeTtl
  • staleWhileRevalidate
  • staleIfError
  • ttlJitter
  • refreshAhead
  • adaptive TTL policies
  • TTL policy return values

Redis writes now use PX, Redis TTL reads use PTTL, and CLI inspect output reports ttlMs.

New stale-preserving expiration APIs

Layercache 2.0.0 adds expiration APIs that mark entries stale without deleting their stale windows:

await cache.expireByTag("product")
await cache.expireByTags(["product", "pricing"])
await cache.expireByPattern("product:*")
await cache.expireByPrefix("product:")
Enter fullscreen mode Exit fullscreen mode

This is useful when you want revalidation to happen, but still want existing cached values to be served during stale-while-revalidate or stale-if-error windows.

Instead of forcing a hard delete, these APIs let the cache degrade more gracefully.

Context-aware cache entry options

contextOptions can now derive TTLs and tags from the resolved cache context:

const cache = new CacheStack({
  layers: [memory],
  contextOptions: ({ key, value, kind }) => ({
    ttl: kind === "set" ? 30_000 : 60_000,
    tags: value.orgId ? [`org:${value.orgId}`] : []
  })
})
Enter fullscreen mode Exit fullscreen mode

This works for fetched values and direct set() calls.

It makes it easier to keep cache metadata close to the data being cached.

Better Redis integration coverage

This release adds real Redis integration coverage for:

  • RedisLayer
  • RedisInvalidationBus
  • RedisTagIndex
  • distributed single-flight
  • multi-instance behavior
  • millisecond TTL handling

The integration suite now runs against a real Redis service through Docker Compose.

Documentation site

Layercache now includes a Next.js docs site with:

  • MDX docs
  • search
  • playground
  • markdown export
  • sitemap
  • robots.txt
  • .well-known API and agent metadata routes

Docs are available at:

https://layercache.flyingsquirrel.me

Smaller npm package

The npm package is now limited to runtime build artifacts.

The package includes:

  • dist/
  • package.json
  • README.md
  • LICENSE

Benchmarks, examples, and stale build artifacts are excluded from the published package.

Migration guide

The main migration step is converting TTL values from seconds to milliseconds.

Before:

ttl: 60
staleWhileRevalidate: 300
staleIfError: 600
Enter fullscreen mode Exit fullscreen mode

After:

ttl: 60_000
staleWhileRevalidate: 300_000
staleIfError: 600_000
Enter fullscreen mode Exit fullscreen mode

If you previously used numeric TTLs, audit every TTL-related option before upgrading.

Install

npm install layercache@2.0.0
Enter fullscreen mode Exit fullscreen mode

Release notes

Full release notes are available here:

https://github.com/flyingsquirrel0419/layercache/releases/tag/v2.0.0

Support the project

If Layercache looks useful, please consider giving the repository a star on GitHub:

https://github.com/flyingsquirrel0419/layercache

Closing

Layercache 2.0.0 is a breaking release, but the goal is simple: make TTL behavior explicit, consistent, and easier to reason about across memory, Redis, disk, CLI output, and documentation.

Top comments (0)