ThrottlingException: Rate exceeded
Fix ThrottlingException "Rate exceeded": set AWS_RETRY_MODE=adaptive, cut API calls, and request a quota increase. Covers Terraform parallelism and DynamoDB.
An error occurred (ThrottlingException) when calling the DescribeInstances operation (reached max retries: 4): Rate exce
Incident Overview
Fix ThrottlingException "Rate exceeded": set AWS_RETRY_MODE=adaptive, cut API calls, and request a quota increase. Covers Terraform parallelism and DynamoDB.
medium fix·5 min read
By Vishvesh Patel·DevOps Engineer·Updated 21 September 2026
An error occurred (ThrottlingException) when calling the DescribeInstances operation (reached max retries: 4): Rate exceeded An error occurred (RequestLimitExceeded) when calling the RunInstances operation: Request limit exceeded. An error occurred (TooManyRequestsException) when calling the Invoke operation: Rate Exceeded. ProvisionedThroughputExceededException
Do this first3 steps
Run these in order. Each one tells you what its output means before you change anything.
• Find out who is actually making the calls
The throttle is account-wide and per region, so the caller exhausting the budget is frequently not the thing reporting the error. Monitoring agents, autoscalers and Terraform refreshes are common culprits.
• Raise the SDK's own retry budget before changing anything else
Adaptive mode adds client-side rate limiting on top of exponential backoff, which is specifically designed for this. It is off by default, and turning it on resolves a lot of intermittent throttling without any code change.
• Check whether the quota is adjustable
Some limits can be raised through Service Quotas and others cannot. API request rates are often not listed at all, which means the answer is to make fewer calls rather than to ask for more.
AWS rate-limits its control plane APIs per account, per region, per service. Exceeding the budget returns a throttling error. The error names vary by service and mean the same thing:
Most use a token bucket: a sustained refill rate plus a burst capacity. Bursts are absorbed, sustained excess is not.
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=DescribeInstances --max-results 20 --query 'Events[].{Time:EventTime,User:Username}' --output tableThe caller is often not you
Throttling is account-wide, so the request that fails is frequently an innocent bystander. Find the real consumer:
For a proper count, query CloudTrail Lake or Athena over the CloudTrail S3 bucket and group by userIdentity.arn. The usual offenders:
The last is worth emphasising: naive retries make throttling worse, not better.
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=DescribeInstances \
--max-results 50 \
--query 'Events[].{Time:EventTime,User:Username}' --output tableTurn on adaptive retries
The SDK defaults are conservative. Adaptive mode adds a client-side rate limiter that slows down when it observes throttling, which is exactly the right behaviour:
Jitter matters. Fixed backoff synchronises every client onto the same retry schedule, so they all retry together and throttle together. The SDK's standard and adaptive modes already randomise; a hand-rolled time.sleep(2 ** n) does not.
export AWS_RETRY_MODE=adaptive export AWS_MAX_ATTEMPTS=10
Make fewer calls
Usually more effective than any retry tuning.
Paginate properly and ask for more per page:
Filter server-side rather than listing everything and filtering locally:
--filters is applied by EC2; --query is applied by the CLI after the response arrives. Only the first reduces API load.
Cache. A list of subnets or AMIs does not change every thirty seconds. Caching for five minutes can remove most of the traffic.
Use events instead of polling. EventBridge notifies you when an instance state changes, which replaces a polling loop entirely.
paginator = ec2.get_paginator("describe_instances")
for page in paginator.paginate(PaginationConfig={"PageSize": 1000}):
...Quotas
Two things to know. Many API rate limits are not exposed in Service Quotas at all and are not adjustable, so no amount of asking helps and the answer is to call less. And resource quotas, such as the number of running vCPUs, are a different thing from rate limits; hitting those produces a different error.
aws service-quotas list-service-quotas --service-code ec2 \ --query 'Quotas[?Adjustable==`true`].[QuotaName,Value]' --output table aws service-quotas request-service-quota-increase \ --service-code ec2 --quota-code L-1216C47A --quota-value 100
Terraform specifically
A large configuration refreshes every resource on every plan, which is a burst of API calls:
-refresh=false is safe for a quick check and not for anything you will apply, since it plans against possibly stale state.
Splitting one enormous configuration into several smaller ones reduces the burst and is usually worth doing for other reasons too.
terraform plan -parallelism=5 # default is 10 terraform plan -refresh=false # skip refresh entirely
DynamoDB and S3 are different
ProvisionedThroughputExceededException is about a table's capacity, not the control plane. Switch the table to on-demand, or raise provisioned capacity, or fix a hot partition key.
S3 SlowDown relates to request rate per prefix. S3 scales automatically but takes time to adapt, so a sudden burst on one prefix throttles. Distributing keys across prefixes helps, and the entropy no longer needs to be at the start of the key as it once did.
A checklist
Frequently Asked Questions
Why am I being throttled when my application makes few API calls?
Because throttling budgets are shared across the whole account and region, not per application. The caller consuming the budget is frequently something else entirely: a monitoring agent polling DescribeInstances, a cluster autoscaler during a scaling event, a Terraform refresh across hundreds of resources, or a retry loop somewhere with no backoff. Use CloudTrail to identify who is actually making the calls before changing anything in the code that happens to be reporting the error.
Does retrying fix throttling?
Retrying with correct exponential backoff and jitter is part of the answer; retrying naively makes it worse. A tight retry loop turns one throttled request into several, and fixed backoff synchronises every client onto the same schedule so they all retry at the same instant. Use the SDK's adaptive retry mode, which adds a client-side rate limiter that slows down when it observes throttling. Set AWS_RETRY_MODE=adaptive and AWS_MAX_ATTEMPTS=10, since the defaults are conservative.
Can I get AWS to raise my API rate limit?
Sometimes. Service Quotas lists which limits are adjustable, and request-service-quota-increase submits a request for those. Many API request rates are not exposed there at all and are not adjustable, in which case the only answer is to make fewer calls. It is also worth distinguishing rate limits from resource quotas: a cap on running vCPUs is a resource quota and produces a different error from a request-rate throttle.
What is the difference between --filters and --query in the AWS CLI?
--filters is sent to the service, which returns only matching results, so it reduces both the response size and the number of paginated calls. --query is a JMESPath expression applied locally by the CLI after the full response has arrived, so it changes what you see and does nothing for API load. When you are being throttled, moving a filter from --query to --filters can substantially reduce the number of requests.
How do I reduce throttling from Terraform?
Lower -parallelism, which defaults to 10, and raise max_retries in the provider block. For a quick plan you can use -refresh=false to skip the refresh entirely, though that plans against potentially stale state and is not appropriate for anything you intend to apply. The structural fix is to split a very large configuration into smaller ones, which reduces the size of each refresh burst and tends to be worth doing for change-safety reasons anyway.
Reference and practice
Learn the underlying concept
Other AWS errors
Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.
Get notified about new tutorials and features.
• Roadmaps
• Interview Prep
• Certifications
• Company
© 2026 DevOpsLesson. All rights reserved.
Need to practice this scenario?
Simulate this error condition and practice recovery commands safely in our in-browser terminal.