LRU Cache TTL Stale-While-Revalidate

Combine LRU eviction with TTL expiry and stale-while-revalidate semantics so hot keys stay warm, expired entries serve stale, and refreshes dedupe.

JavascriptData Fetching

Code

snippet
import { LRUCache } from 'lru-cache';

const cache = new LRUCache({
  max: 500,
  ttl: 60_000,
  staleTtl: 300_000,
  allowStale: true,
  fetchMethod: async (key) => {
    const res = await fetch('https://api.example.com/rates/' + key);
    if (!res.ok) throw new Error('upstream ' + res.status);
    return res.json();
  },
});

const inflight = new Map();

async function getRate(currency) {
  const value = await cache.fetch(currency);
  return value;
}

async function revalidate(key, loader) {
  if (inflight.has(key)) return inflight.get(key);

  const task = loader()
    .then((fresh) => { cache.set(key, fresh); return fresh; })
    .finally(() => { inflight.delete(key); });

  inflight.set(key, task);
  return task;
}

const usd = await getRate('usd');
const again = await getRate('usd');
console.log('rate:', usd.rate, 'second read:', again.rate);