Tips > Data, APIs & Webhooks

Cache API Responses to Avoid Redundant Calls

If your workflow calls an API whose response does not change frequently, cache the response and serve from cache on subsequent runs.

TipIntermediate2 min read

If your workflow calls an API whose response does not change frequently, cache the response and serve from cache on subsequent runs. Use a Google Sheet, database table, or even a static file as your cache layer. Include a TTL (time-to-live) so stale data refreshes automatically.

Real-world example: A workflow converts prices from USD to EUR. Exchange rates change daily, but the workflow runs every time a product is viewed -- hundreds of times per day. Cache the exchange rate with a 24-hour TTL.

// Code node: "Check Exchange Rate Cache"
const cacheKey = 'USD_EUR';
const cacheTTLHours = 24;

// $json comes from a Google Sheets or DB lookup for the cache entry
const cacheEntry = $input.first().json;

if (cacheEntry && cacheEntry.rate && cacheEntry.cached_at) {
  const cachedAt = new Date(cacheEntry.cached_at);
  const ageHours = (Date.now() - cachedAt.getTime()) / (1000 * 60 * 60);

  if (ageHours < cacheTTLHours) {
    // Cache hit -- return cached rate
    return [{
      json: {
        rate: cacheEntry.rate,
        source: 'cache',
        cached_at: cacheEntry.cached_at,
        expires_in_hours: Math.round(cacheTTLHours - ageHours)
      }
    }];
  }
}

// Cache miss or expired -- flag for refresh
return [{
  json: {
    rate: null,
    source: 'miss',
    needs_refresh: true
  }
}];
```text
Use an IF node to branch: cache hit skips the API call, cache miss calls the exchange rate API and then updates the cache:

```json
// HTTP Request node: "Fetch Fresh Rate" (only on cache miss)
{
  "method": "GET",
  "url": "https://api.exchangerate-api.com/v4/latest/USD",
  "options": { "timeout": 5000 }
}
```text
```javascript
// Code node: "Update Cache" (after fetching fresh rate)
const freshRate = $input.first().json.rates.EUR;

return [{
  json: {
    key: 'USD_EUR',
    rate: freshRate,
    cached_at: new Date().toISOString()
  }
}];
// Then write this to your Google Sheet or database
```text
```yaml
Cost savings:
  Without cache: 500 API calls/day x $0.001 = $0.50/day = $15/month
  With cache:    1 API call/day   x $0.001 = $0.001/day = $0.03/month
  Savings: 99.8%
```text
This pattern works for any data that changes infrequently: geocoding results, company info lookups, configuration fetches, or any reference data.

**Related:** [Use Structured Output (JSON Mode) for Parseable Responses](../ai-and-llm-integration/01-use-structured-output-json-mode-for-parseable-responses.md) | [Configure Payload Size and Binary Data Mode for Large Files](../performance-and-large-files/01-configure-payload-size-and-binary-data-mode-for-large-files.md)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.