Skip to content

lease-cache ​

Read-through caching on Valkey or Redis with leases: one load per key across every instance, and a load that finishes after an invalidation never caches its outdated value.

ts
import { 
Redis
} from 'ioredis';
import {
LeaseCache
} from 'lease-cache';
const
cache
= new
LeaseCache
({
connection
: new
Redis
('redis://valkey:6379'),
prefix
: 'users',
ttlMs
: 60_000,
leaseMs
: 5000,
pollMs
: 50,
waitMs
: 2000,
}); const
user
= await
cache
.
get
(`user:${
id
}`, async () =>
db
.
users
.
find
(
id
));
const user: User | null
await
db
.
users
.
update
(
id
, {
name
: 'Ada' });
await
cache
.
invalidate
(`user:${
id
}`);

Get started →

Features ​

  • One load per key, across every instance: the first reader to miss takes a lease and loads. Readers in every other process wait for its value instead of loading too.
  • No outdated values after an invalidation: a load that started before invalidate() returns to its caller, but can't cache what it read. See Invalidation.
  • Optionally, no waiting after an invalidation: with staleMs, the old value is kept as stale, and readers that would wait on the next load return it instead.
  • A failed or stuck load holds no one up for long: a failed load frees its lease right away, and readers stop waiting after waitMs.
  • No client dependency: anything with an eval command works. ioredis and iovalkey fit as they are, and node-redis and Valkey GLIDE need a few lines. See Clients. Keys use hash tags, so it works on a cluster.

Leases are the mechanism memcache uses at Facebook (Scaling Memcache at Facebook, section 3.2.1), done here with a few small Lua scripts. It is the narrow part of a cache, not a whole one: pair it with a fuller cache for a memory tier or stale-while-revalidate on expiry, as the read-through cache demo does with BentoCache.

Compared to ​

lease-cacheBentoCache, cache-manager, cachified
Concurrent misses in one instanceone loadone load
Concurrent misses across instancesone loadone per instance
Load finishing after an invalidationnot cachedcached until it expires
Memory tier, stale-while-revalidate on expiry, many stores❌✅

See Why lease-cache for the full comparison.