Core concepts

Cache invalidation

Warming data is only half the job. Glacier also has to let it go at the right time, so users never see something stale.


Time-based expiry

Every entry has a ttl. When it elapses, the entry is marked stale and evicted on the next sweep. Set a global default and override per call:

glacier.prefetch('pricing:plans', { ttl: '1h' })

Short TTLs keep data fresh at the cost of more re-warming; long TTLs do the opposite. Pick per data type, not globally.

Tag-based invalidation

Group related entries with tags and drop them all at once — useful when one write affects many cached reads:

glacier.prefetch('orders:user:42', { tags: ['user:42'] })

// Later, after the user changes something:
glacier.invalidate({ tag: 'user:42' })

Invalidate on mutation

The cleanest pattern is to invalidate right where you mutate, so reads can never lag writes:

async function updateProfile(id, data) {
  await api.patch(`/users/${id}`, data)
  glacier.invalidate({ tag: `user:${id}` })
}

Glacier is never the source of truth

If an entry is missing or has been invalidated, Glacier falls through to your underlying fetch. The worst case of an over-eager invalidation is a single cache miss — never incorrect data.

Manual purge

To clear everything — for example on logout — call glacier.clear(). For a single key, glacier.invalidate({ key }).

See the full signature in the Glacier.invalidate() reference.

Previous
Predicting user behavior