TTL
Optional and lazy time-to-live, checked on get/has/peek, no background sweep timer.
TTL (time-to-live) is optional and lazy — there is no background timer sweeping expired entries. Expiry is checked only when an entry is touched via get, has, or peek. An entry with no applicable ttl never expires.
Cache-Wide Default
Pass ttl (milliseconds) to createCache(...) to apply it to every entry that doesn’t specify its own:
const cache = createCache<string, number>(100, { ttl: 60_000 }); // 60s default
cache.set("a", 1); // expires in 60s
Per-Entry Override
Pass { ttl } as the third argument to set(...) to override the cache-wide default for that entry:
const cache = createCache<string, number>(100, { ttl: 60_000 });
cache.set("a", 1); // expires in 60s (cache-wide default)
cache.set("b", 2, { ttl: 5_000 }); // expires in 5s, overriding the default
No Default, No Expiry
Omitting ttl on both the cache and the entry means that entry never expires:
const cache = createCache<string, number>(100); // no ttl configured
cache.set("a", 1); // never expires
How Expiry Is Checked
Each entry stores an absolute expiresAt timestamp (Date.now() + ttl at the time of set). get, has, and peek compare it against the current time on every call:
- Expired: the entry is removed from the store,
onEvictfires if configured, and the call returnsundefined(get/peek) orfalse(has). - Live: the call proceeds normally.
const cache = createCache<string, number>(2, { ttl: 100 });
cache.set("a", 1);
// ... 101ms later ...
cache.get("a"); // undefined — expired and removed
cache.has("a"); // false
Because expiry is lazy, an expired entry that is never read stays in the underlying store (and counts toward nothing, since size only counts live entries) until the next touch or a capacity eviction reclaims the slot.
Interaction with size
size only counts live (non-expired) entries — an expired entry that hasn’t been touched yet is not counted:
const cache = createCache<string, number>(2, { ttl: 100 });
cache.set("a", 1);
// ... 101ms later, "a" still physically in the store ...
cache.size; // 0 — expired entries don't count
Iteration Skips Expired Entries
keys(), values(), entries(), and [Symbol.iterator]() all skip expired entries without removing them from the store or firing onEvict — see Iteration.
See Also
onEvict— fires when a TTL expiry is discovered- Capacity and Eviction — the other way entries leave the cache