← All articles

API Security & Rate Limiting: Best Practices for Resilient Apps

Published 1 Oct 2026

Build resilient client applications. Learn how to store API credentials securely in environment variables, handle 429 rate limit errors with exponential backoff, and leverage status monitoring.


Connecting to external APIs is one of the most powerful ways to build modern software. However, without proper security hygiene and resilient client design, integrations can become single points of failure.

Follow these proven engineering best practices to keep your apps secure, compliant, and rock-solid under heavy load.


1. Protect Your API Keys Like Passwords

Your marketplace API key grants access to your active subscriptions and balances. Leaking a key can lead to unauthorized usage and quota exhaustion.

  • Never commit keys to version control: Add .env and configuration files to your .gitignore.
  • Use Server-Side Proxies: If your frontend (React, Vue, mobile app) needs API data, call your own backend endpoint first, and have your backend attach the X-API-Key to the marketplace request.
  • Rotate Compromised Keys Immediately: If you suspect a key was accidentally exposed, generate a fresh key in Account > API Keys and revoke the old one instantly.

2. Respect the Three Rate-Limit Windows

Our gateway monitors requests across three distinct windows to keep services healthy for everyone:

  • Per Minute: Protects upstreams against sudden burst traffic or infinite loops.
  • Per Day: Prevents daily runaway spikes.
  • Per Month: Your contracted monthly allowance.

When your client hits a rate limit, the gateway returns an HTTP 429 Too Many Requests status code with explanatory headers.


3. Implement Exponential Backoff with Jitter

Never retry failed requests in a tight loop—this creates a "thundering herd" problem that exacerbates downtime. Instead, implement exponential backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
  let attempt = 0;
  while (attempt < maxRetries) {
    try {
      const response = await fetch(url, options);
      if (response.status === 429 || (response.status >= 500 && response.status <= 504)) {
        // Calculate backoff: 2^attempt * 1000ms + random jitter
        const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;
        console.warn(`Rate limited or transient server error. Retrying in ${Math.round(delay)}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
        attempt++;
        continue;
      }
      return response;
    } catch (err) {
      if (attempt === maxRetries - 1) throw err;
      attempt++;
    }
  }
}

4. Cache Predictable Responses

Many API calls return data that rarely changes—such as currency exchange rates, country codes, or city weather.

  • Implement an in-memory cache (like Redis, Memcached, or local file cache).
  • Cache successful responses for a sensible Time-to-Live (TTL), e.g., 5 to 60 minutes.
  • Caching saves substantial quota, reduces your monthly bill, and drops client latency to near zero!

5. Check Upstream Health Proactively

Before debugging your own code during an unexpected error, check the marketplace API Status page (/health.php). It provides real-time reachability, error codes, and latency checks for every provider on the platform.

Build with APIs?
Browse production-ready APIs with instant keys.
Browse APIs