DEV Community

Jonas Hämmerle
Jonas Hämmerle

Posted on

Caching exchange rates correctly: per-day TTL, not per-request memoization

If you're converting to several currencies at once — a pricing page showing a product in 8 currencies, say — the naive approach is one /convert call per currency pair. That works, but it's leaving an easy optimization on the table: ECB-sourced rates update once per business day, so there's no reason to be making fresh network calls more often than that.

The right cache key isn't "this specific conversion," it's "the rate table for this base currency, as of today's date":

const rateCache = new Map(); // key: `${base}:${isoDate}`

async function getRatesForDay(base) {
  const today = new Date().toISOString().slice(0, 10);
  const key = `${base}:${today}`;
  if (rateCache.has(key)) return rateCache.get(key);

  const res = await fetch(`https://currency-api.p.rapidapi.com/v1/rates?base=${base}`, {
    headers: { "X-RapidAPI-Key": key_env, "X-RapidAPI-Host": "currency-api.p.rapidapi.com" },
  });
  const data = await res.json();
  rateCache.set(key, data);
  return data;
}
Enter fullscreen mode Exit fullscreen mode

One call per base currency per day gets you every target currency's rate in that response — /v1/rates returns the full table, not just one pair — so converting to 8 currencies from a cached table is 8 in-memory lookups, not 8 network round-trips.

Two things worth being careful about: cache the date the rate was published, not the date you fetched it (a request right after midnight UTC might still be serving yesterday's ECB publish if today's hasn't landed yet), and don't cache across a process restart without also persisting the date key — a stale in-memory cache that outlives its day is exactly the silent-wrong-number problem you're trying to avoid.

Currency API's /v1/rates endpoint is built for this pattern — pull the whole table once, cache it client-side for the day, and reserve /v1/convert for one-off single conversions where pulling the whole table would be overkill. Sibling APIs on the same account: Validate and QR API.

Top comments (0)