# AWS API Rate Limit Exceeded

Common Error Patterns

Rate limit errors appear as:

bash
RequestLimitExceeded: Request limit exceeded.
bash
ThrottlingException: Rate exceeded
bash
SlowDown: Please reduce your request rate.
bash
API: ec2:DescribeInstances Rate exceeded

Root 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:

bash
aws service-quotas request-service-quota-increase \
  --service-code ec2 \
  --quota-code L-12345678 \
  --desired-value 1000

3. 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:

python
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

bash
# 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:00Z

CloudTrail Analysis

bash
# Find throttled requests
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=ThrottlingException \
  --max-results 50

Retry 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

ServiceDefault RateQuota Code Prefix
EC2~100/secL-
S33,500 PUT/5500 GET per prefixN/A
DynamoDBvaries by modeL-
Lambda1,000 concurrentL-
CloudWatch1,000 TPSL-

Prevention Tips

  1. 1.Use AWS SDK adaptive retry mode
  2. 2.Implement exponential backoff
  3. 3.Distribute requests across time/regions
  4. 4.Request quota increases proactively
  5. 5.Monitor throttling metrics in CloudWatch
  • [AWS Lambda Timeout](#)
  • [AWS S3 Access Denied](#)
  • [AWS IAM Permission Denied](#)