EZRate
Sign in

Financial API Failover Strategy: Timeouts, 429s, Staleness and Fallbacks

A financial API failover strategy for FX feeds: error classes, timeouts, retries with backoff, 429 and Retry-After, stale caches and data-quality guards.

Arian Asadi
· Writer and Market Analyst
Published 3 November 2026, 20:00 · 3 min read
Financial API Failover Strategy
Key takeaways
  • Classify errors: client errors (401/403/422) need a fix, 429 needs backing off, 5xx and timeouts can be retried.
  • Serve from a cache with a last-good copy, mark data as stale and never show zero or blank prices.
  • Guard against bad data as well as missing data: low-source flags, jump limits and timestamps.

A pricing page that crashes when the data provider hiccups is bad. A pricing page that silently shows a wrong number is worse. A solid financial API failover strategy covers both: availability problems and data-quality problems. This guide lays out the patterns with EZRate’s error model as the example.

i
EZRate API
This guide uses the EZRate currency and gold price API: full documentation, code samples and a free key are on the API page.
★
Short answer
Set a timeout (≈10 s), retry only 5xx and network errors with exponential backoff, back off on 429 using Retry-After, and treat 401/403/422 as bugs to fix. Always read from a cache that keeps a last-good copy; show it with a “stale” notice if the feed is down. Check low_sources and updated_at, cap sudden jumps, and keep a secondary source for critical flows.

Part of the Iranian Rial exchange rate API guide.

Error model

json
{ "error": { "code": "rate_limited", "message": "…" }, "meta": { "reset_at": "2026-10-20T00:00:00Z" } }
Status / codeMeaningAction
401 invalid_api_keyKey missing or wrongFix configuration; do not retry
403 forbiddenIP or domain not allowed for the keyFix key restrictions; do not retry
404 not_foundUnknown symbol or marketFix the request
422 validation_failedBad parameter; fields explainsFix the request
429 rate_limitedPer-second or quota limit hitWait Retry-After; check caching
5xx / timeoutTransient failureRetry with backoff, then fall back

Response headers X-RateLimit-Remaining-Day, X-RateLimit-Remaining-Month and Retry-After let you act before you hit a wall. Full details: JSON reference.

Retry with backoff

typescript
async function getJson(url: string, key: string, tries = 3): Promise<any> {
  for (let i = 0; i < tries; i++) {
    try {
      const r = await fetch(url, { headers: { "X-API-Key": key }, signal: AbortSignal.timeout(10_000) });
      if (r.ok) return r.json();
      if (r.status === 429) {
        const wait = Number(r.headers.get("retry-after") ?? 60);
        throw Object.assign(new Error("rate_limited"), { retryAfter: wait, final: true });
      }
      if (r.status < 500) throw Object.assign(new Error(`client ${r.status}`), { final: true });
    } catch (e: any) {
      if (e.final || i === tries - 1) throw e;
    }
    await new Promise(res => setTimeout(res, 500 * 2 ** i + Math.random() * 250)); // jitter
  }
}

Cache with a last-good copy

Sequence diagram: request → fresh cache hit; miss → upstream; upstream fails → last-good copy marked stale
Stale-while-revalidate for price data
  • Fresh key with TTL = freshness_sec.
  • Last-good key with a long TTL (e.g. 24 h).
  • Background refresh from a scheduler, so user requests never wait on the upstream.
  • Stale flag in your own payload so the UI can show “last updated 14 minutes ago”.

Implementations: Laravel, Python/Django, Node.js.

Data-quality guards

GuardRule of thumb
Low sourcesIf low_sources is true, display with a badge and pause automatic repricing
StalenessIf updated_at is older than N minutes, show a warning
Jump limitIf a price moves more than X% since the last accepted value, hold it for review
Sanity boundsReject zero, negative or wildly out-of-range values
Unit assertionCheck quote is what you expect (IRT vs IRR)

EZRate already applies median filtering and a jump guard upstream (see outlier detection); your own guards protect against integration bugs and edge cases.

US Dollar271,740Toman−0.02%

Secondary sources

For flows where downtime costs money (checkout, trading), keep a second source. Use it only when the primary is stale beyond a threshold, log every switch, and never average two sources with different methodologies without understanding them.

Monitoring

  • Alert on cache age, not just HTTP errors.
  • Track 429s: they usually mean caching broke.
  • Track the remaining quota from headers or /usage.
  • Synthetic check: request one symbol every minute from outside your network.
Monitoring dashboard with cache age, error rate and remaining quota panels
What to monitor

Designing for degraded modes

Decide in advance how each part of your product behaves when data is old: product pages keep showing prices with a notice; checkout may refuse to finalise a price older than a threshold; automated repricing pauses. Writing these rules down turns an outage from an emergency into a documented, expected state.

Practise these modes too: occasionally block the upstream host in staging and confirm that pages, checkout and jobs behave exactly as documented.

Related live rates: US dollar rate, 18K gold price, Emami coin price.

Should I retry a 429?
Only after the Retry-After delay; frequent 429s mean your caching needs fixing.
Which errors are safe to retry?
Timeouts, network errors and 5xx responses, with exponential backoff.
What should users see if the feed is down?
The last good prices with a clear “last updated” time, never zero or blank.
Do I need a second data source?
For revenue-critical flows, a secondary source used only on primary staleness is a good safety net.
Arian Asadi
I studied economics and developed an interest in financial markets, exchange rates, and economic developments during my university years. Throughout my professional career, I have focused particularly on foreign exchange markets, gold, international money transfers, and the impact of economic developments on prices. In the articles I write, I strive to present information about exchange rates and financial markets in a clear and accessible way, based on verifiable data and market trends. My goal is to help readers gain a clearer understanding of market conditions before making decisions about buying, selling, or transferring currencies.
All posts by author →

Comments (0)

Comments are shown after review. Sign-in is needed to send.

Related

API & Developers
Currency Exchange WebSocket API or REST Polling? A Node.js Guide
API & Developers
Live Exchange Rates in Google Sheets and Excel via API (No Add-ons)
API & Developers
Historical USD to IRR Data: Free-Market Candles via API for Analysts