HTTP 429 "Too Many Requests" means the API is rate-limiting your client because it has received more requests than allowed in a given window. To resolve and prevent it, follow these diagnostic and mitigation steps.
Immediate checks - Inspect the API response headers for Retry-After (or X-RateLimit-* headers) to see how long to wait before retrying. - Confirm which endpoint triggered the limit and whether limits differ by endpoint or method. - Check your provider dashboard for rate-limit and quota details and recent usage spikes.
Rate-limit handling strategies
-
Respect Retry-After: if present, delay retries for the specified time.
-
Implement exponential backoff with jitter to avoid synchronized retries across clients.
-
Limit concurrency: reduce parallel requests from threads/processes or add a request queue.
-
Batch requests where possible or use bulk endpoints to reduce call volume.
-
Cache responses for repeated requests to avoid unnecessary API calls.
-
Debounce frequent client actions (e.g., typing-triggered requests) and aggregate them server-side.
-
Add server-side throttling to prevent client bursts from exhausting quota.
Common causes to investigate
-
Background jobs or cron tasks sending bursts of requests.
-
Multiple services or deployments sharing the same API key.
-
Endless retry loops where retries are immediate and unbounded.
-
Missing or incorrect use of pagination causing repeated full-data fetches.
-
Webhook re-delivery storms or misconfigured clients.
Example exponential backoff (pseudocode)
- Use sleep = base * 2^attempt + random_jitter, cap at max_delay, and stop after max_attempts.
JavaScript example:
const maxAttempts = 6;
const baseDelay = 500; // ms
async function requestWithBackoff(fn) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (err) {
if (err.status !== 429) throw err;
const jitter = Math.random() * 100;
const delay = Math.min(baseDelay * 2 ** attempt + jitter, 10000);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error(‘Max retry attempts reached’);
}
Python example:
import time, random
def request_with_backoff(func):
max_attempts = 6
base = 0.5
for attempt in range(max_attempts):
try:
return func()
except ApiError as e:
if e.status_code != 429:
raise
jitter = random.random() * 0.1
delay = min(base * (2 ** attempt) + jitter, 10)
time.sleep(delay)
raise RuntimeError("Max retries reached")
Operational recommendations
-
Add monitoring/alerts for 429s and unusual request spikes.
-
Log request timestamps, endpoints, and API key usage to identify patterns.
-
If appropriate, request a quota increase from the API provider with evidence of legitimate usage patterns.
-
Rotate or segregate API keys per service to isolate noisy clients.
-
Ensure idempotency for operations so retries don’t cause side effects.
If you can share the response headers or a snippet of the request flow (no secrets or full keys), I can suggest targeted changes to reduce 429s.