How to Implement Retry with Exponential Backoff for Cloud API 429 Errors in Python
Implement a retry-with-backoff loop in Python to handle 429 throttling errors from cloud APIs, using exponential delay between attempts.
pip install requests
Python code
30 linesimport time
import random
import requests
def api_call(attempt):
"""Mock cloud API that returns 429 for the first two attempts."""
if attempt < 2:
return 429, "Too Many Requests"
return 200, {"data": "success"}
def retry_with_backoff(api_func, max_retries=3, base_delay=0.1):
for attempt in range(max_retries):
status, body = api_func(attempt)
if status == 429:
delay = base_delay * (2 ** attempt)
print(f"Attempt {attempt + 1}: 429, retrying in {delay:.2f}s")
time.sleep(delay)
else:
print(f"Attempt {attempt + 1}: {status} - {body}")
return status, body
print("Max retries exceeded")
return None
if __name__ == "__main__":
random.seed(42)
result = retry_with_backoff(lambda attempt: api_call(attempt))
print("Final result:", result)
Output
Attempt 1: 429, retrying in 0.10s
Attempt 2: 429, retrying in 0.20s
Attempt 3: 200 - {'data': 'success'}
Final result: (200, {'data': 'success'})
How it works
The retry_with_backoff function loops through a maximum number of attempts, calling the API function each time. When the status code is 429, it calculates a delay using exponential backoff (base_delay * (2 ** attempt)) and sleeps to respect the throttle. If the call succeeds (status != 429), it returns the result immediately, avoiding unnecessary waits. The loop tracks the attempt index so the delay grows with each retry, a standard pattern in cloud SDKs. Using random.seed(42) here is optional—it just makes the example reproducible, but the actual retry logic does not rely on randomness.
Common mistakes
- Not sleeping between retries, causing immediate hammering of the API
- Using a fixed delay instead of exponential backoff, which increases load on already-throttled services
- Forgetting to handle other error status codes (e.g., 5xx) that should also be retried
- Exceeding resource limits by retrying indefinitely without a max attempts cap
Variations
- Use `tenacity` library with `@retry(wait=wait_exponential())` to simplify retry logic
- Parse the `Retry-After` header from the 429 response to set a custom delay
Real-world use cases
- Making authenticated calls to AWS, GCP, or Azure APIs that rate-limit requests per second
- Fetching data from REST endpoints like GitHub or Stripe that return 429 when quotas are exceeded
- Processing large batches of API requests in a data pipeline where throttling is common
Sponsored
More from Cloud + Python
- Build a URL Shortener Client with Python medium
- Create a Cloud Storage Helper Class in Python easy
- Create a Data Helper Class for Beginners in Python easy
- Cross Account Role Chaining Mock Credentials in Python medium
- Exponential Backoff with Jitter for Cloud API Calls in Python medium
- Generate Mock CloudFormation Stack Events in Python easy
Keep learning
Related tutorials and quizzes for this topic.