# AWS API Rate Limit Exceeded
Common Error Patterns
Rate limit errors appear as:
RequestLimitExceeded: Request limit exceeded.ThrottlingException: Rate exceededSlowDown: Please reduce your request rate.API: ec2:DescribeInstances Rate exceededRoot Causes and Solutions
1. Exceeded API Request Quota
Each AWS service has request rate limits.
Solution:
Implement exponential backoff with jitter:
```python import time import random import boto3
def with_retry(func, max_retries=5, base_delay=1): for attempt in range(max_retries): try: return func() except Exception as e: if 'Throttling' in str(e) or 'Rate' in str(e): if attempt == max_retries - 1: raise delay = base_delay * (2 ** attempt) + random.uniform(0, 1) time.sleep(delay) else: raise
# Usage ec2 = boto3.client('ec2') result = with_retry(lambda: ec2.describe_instances()) ```
Use AWS SDK built-in retry:
```python from botocore.config import Config
config = Config( retries={ 'max_attempts': 10, 'mode': 'adaptive' } )
ec2 = boto3.client('ec2', config=config) ```
2. Service-Specific Limits
Different services have different rate limits.
Solution:
Check service quotas:
```bash # List all quotas for EC2 aws service-quotas list-service-quotas \ --service-code ec2 \ --region us-east-1
# Check specific quota aws service-quotas get-service-quota \ --service-code ec2 \ --quota-code L-12345678 ```
Request quota increase:
aws service-quotas request-service-quota-increase \
--service-code ec2 \
--quota-code L-12345678 \
--desired-value 10003. Concurrent Request Limits
Too many simultaneous requests.
Solution:
Implement request batching:
```python import boto3 from concurrent.futures import ThreadPoolExecutor, as_completed
ec2 = boto3.client('ec2')
def describe_instance(instance_id): try: return ec2.describe_instances(InstanceIds=[instance_id]) except Exception as e: return {'error': str(e), 'instance_id': instance_id}
# Limit concurrent requests with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(describe_instance, id) for id in instance_ids] results = [f.result() for f in as_completed(futures)] ```
Use pagination for large result sets:
paginator = ec2.get_paginator('describe_instances')
for page in paginator.paginate():
for reservation in page['Reservations']:
for instance in reservation['Instances']:
print(instance['InstanceId'])4. Burst vs. Sustained Rate Limits
Exceeded sustained rate limits after burst.
Solution:
Distribute requests evenly:
```python import time
def rate_limited_requests(items, requests_per_second=10): delay = 1.0 / requests_per_second results = [] for item in items: result = make_api_call(item) results.append(result) time.sleep(delay) return results ```
5. Cross-Account Throttling
Multiple accounts hitting shared limits.
Solution:
Some limits are regional or account-based. Distribute load:
```python # Use multiple accounts/regions clients = [ boto3.client('ec2', region_name='us-east-1'), boto3.client('ec2', region_name='us-west-2'), ]
def round_robin_request(clients, index): client = clients[index % len(clients)] return client.describe_instances() ```
Service-Specific Strategies
EC2 API
```bash # Check EC2 API rate limits aws service-quotas get-service-quota \ --service-code ec2 \ --quota-code L-12345678
# Common EC2 quotas # L-12345678: DescribeInstances # L-12345679: RunInstances # L-1234567A: StartInstances ```
Best practices: - Use DescribeInstances with Filters instead of multiple calls - Batch instance operations - Use EventBridge for state changes
S3 API
```bash # S3 has per-prefix limits # Distribute objects across prefixes
# Good: Multiple prefixes s3://bucket/prefix1/object1 s3://bucket/prefix2/object2 s3://bucket/prefix3/object3
# Bad: Single prefix s3://bucket/prefix/object1 s3://bucket/prefix/object2 s3://bucket/prefix/object3 ```
DynamoDB
```bash # Check DynamoDB limits aws dynamodb describe-limits
# Use on-demand mode for variable traffic aws dynamodb update-table \ --table-name my-table \ --billing-mode PAY_PER_REQUEST ```
Lambda
```python # Lambda concurrent execution limits # Use reserved concurrency
aws lambda put-function-concurrency \ --function-name my-function \ --reserved-concurrent-executions 100 ```
Monitoring Rate Limits
CloudWatch Metrics
# Monitor throttling
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name RequestCount \
--dimensions Name=Service,Value=EC2 \
--statistics Sum \
--period 60 \
--start-time 2024-01-01T00:00:00Z \
--end-time 2024-01-01T01:00:00ZCloudTrail Analysis
# Find throttled requests
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=ThrottlingException \
--max-results 50Retry Best Practices
Exponential Backoff with Jitter
```python import time import random
def exponential_backoff_with_jitter(attempt, base_delay=1, max_delay=60): delay = min(base_delay * (2 ** attempt), max_delay) jitter = random.uniform(0, delay * 0.1) return delay + jitter
def api_call_with_retry(func, max_attempts=5): for attempt in range(max_attempts): try: return func() except Exception as e: if 'Throttl' in str(e): if attempt == max_attempts - 1: raise delay = exponential_backoff_with_jitter(attempt) time.sleep(delay) else: raise ```
Circuit Breaker Pattern
```python from datetime import datetime, timedelta import time
class CircuitBreaker: def __init__(self, failure_threshold=5, reset_timeout=60): self.failures = 0 self.failure_threshold = failure_threshold self.reset_timeout = reset_timeout self.last_failure = None self.state = 'closed'
def call(self, func): if self.state == 'open': if datetime.now() - self.last_failure > timedelta(seconds=self.reset_timeout): self.state = 'half-open' else: raise Exception('Circuit breaker is open')
try: result = func() if self.state == 'half-open': self.failures = 0 self.state = 'closed' return result except Exception as e: self.failures += 1 self.last_failure = datetime.now() if self.failures >= self.failure_threshold: self.state = 'open' raise ```
Quick Reference
| Service | Default Rate | Quota Code Prefix |
|---|---|---|
| EC2 | ~100/sec | L- |
| S3 | 3,500 PUT/5500 GET per prefix | N/A |
| DynamoDB | varies by mode | L- |
| Lambda | 1,000 concurrent | L- |
| CloudWatch | 1,000 TPS | L- |
Prevention Tips
- 1.Use AWS SDK adaptive retry mode
- 2.Implement exponential backoff
- 3.Distribute requests across time/regions
- 4.Request quota increases proactively
- 5.Monitor throttling metrics in CloudWatch
Related Articles
- [AWS Lambda Timeout](#)
- [AWS S3 Access Denied](#)
- [AWS IAM Permission Denied](#)