Skip to content
Zap Studio
cache
Esc
navigateopen⌘Jpreview
On this page

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, onEvict fires if configured, and the call returns undefined (get/peek) or false (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

Last updated on September 21, 2026

Was this page helpful?