Lambda reserved concurrency is a feature that lets you guarantee a certain number of execution environments for a specific Lambda function. It prevents other functions in the same region and account from stealing its capacity and, more importantly, it stops this function from impacting other functions if it goes rogue and spins up too many instances. The surprise is that setting reserved concurrency isn’t just about guaranteeing capacity for your function; it’s often the direct cause of throttling for other functions when you don’t have enough total concurrency allocated to your account.
Let’s see it in action. Imagine you have two functions, high-traffic-function and low-traffic-function.
// AWS Lambda Configuration for high-traffic-function
{
"FunctionName": "high-traffic-function",
"ReservedConcurrency": 500, // Guarantees 500 concurrent executions
"Memory": 128,
"Timeout": 300
}
// AWS Lambda Configuration for low-traffic-function
{
"FunctionName": "low-traffic-function",
"ReservedConcurrency": 10, // Guarantees 10 concurrent executions
"Memory": 128,
"Timeout": 300
}
In this setup, high-traffic-function is guaranteed to have up to 500 concurrent executions available. low-traffic-function is guaranteed 10. This means, between these two functions alone, you’ve "reserved" 510 concurrent executions.
Now, consider your AWS account’s unreserved account concurrency. This is the pool of execution environments available to all other Lambda functions in your region that don’t have reserved concurrency set, and it’s also the overflow capacity for functions that do hit their reserved limit (up to the account limit). The default unreserved account concurrency limit is 1000 per region.
If high-traffic-function suddenly receives 600 concurrent requests, it will use its 500 reserved slots. The remaining 100 requests will try to find capacity in the unreserved account pool. If low-traffic-function is already using its 10 reserved slots, those 100 requests will compete for the remaining unreserved capacity. If the unreserved pool is already depleted by other functions, these 100 requests for high-traffic-function will be throttled, even though high-traffic-function itself is not exceeding its reserved concurrency.
The problem arises when the sum of your reserved concurrency for all functions, plus the anticipated load on your unreserved concurrency, exceeds your account’s concurrency limit for that region. The account concurrency limit is a hard cap.
Here’s the breakdown:
- Account Concurrency Limit: This is the absolute maximum number of concurrent Lambda executions your AWS account can have across all functions in a given region. The default is 1000. You can request an increase via AWS Support.
- Reserved Concurrency: When you set reserved concurrency for a function (e.g.,
my-critical-functionto 200), you are dedicating 200 execution environments exclusively to that function. These 200 slots are removed from the general pool of unreserved concurrency. This means your available unreserved concurrency is nowAccount Concurrency Limit - Sum of all Reserved Concurrency. - Unreserved Concurrency: This is the pool of execution environments available to functions without reserved concurrency, and it acts as a fallback for functions that hit their reserved limit (up to the account limit).
The Throttle Scenario:
You’re getting TooManyRequestsException (HTTP 429) errors on low-traffic-function.
-
Diagnosis:
- Check the
ConcurrentExecutionsmetric forlow-traffic-functionand all other functions in the region. - Check the
Throttlesmetric forlow-traffic-functionand all other functions. - Navigate to AWS Lambda -> Quotas. Under "Concurrency", look at the "Concurrent executions" quota for your region. This is your account limit.
- Sum the
ReservedConcurrencyvalues for all Lambda functions in that region. You can get this by runningaws lambda list-functions --query "Functions[*].[FunctionName, ReservedConcurrency]" --output textand then summing the second column (ignoring functions withNonefor reserved concurrency). Let’s say this sum isTotalReservedConcurrency. - Calculate your available unreserved concurrency:
AvailableUnreserved = AccountConcurrencyLimit - TotalReservedConcurrency. IfTotalReservedConcurrencyis very close to or exceedsAccountConcurrencyLimit, you have little to no unreserved capacity.
- Check the
-
Common Cause 1: Insufficient Account Concurrency Limit.
- Diagnosis: Your
AccountConcurrencyLimit(e.g., 1000) is less than the sum of allReservedConcurrencysettings plus the peak concurrent executions needed by your unreserved functions. - Fix: Request an increase for your "Concurrent executions" quota for the affected region via the AWS Support Center.
- Why it works: This directly raises the hard ceiling, allowing more total executions across your account.
- Diagnosis: Your
-
Common Cause 2: Over-allocation of Reserved Concurrency.
- Diagnosis: The sum of
ReservedConcurrencyfor your functions (TotalReservedConcurrency) is too high, leaving insufficientAvailableUnreservedfor other functions that need it. For example, ifAccountConcurrencyLimitis 1000, and you’ve setReservedConcurrencyto 950 for other functions, only 50 slots are left for everything else. - Fix: Reduce the
ReservedConcurrencyfor functions that don’t absolutely require it to a lower value, or set it to0(which means it will use the unreserved pool). For example, forlow-traffic-functionthat currently hasReservedConcurrency: 50, reduce it to10.aws lambda put-function-concurrency --function-name low-traffic-function --reserved-concurrency 10. - Why it works: This frees up execution environments from being permanently allocated, making them available to the general unreserved pool.
- Diagnosis: The sum of
-
Common Cause 3: A Single Function’s Reserved Concurrency is Too High.
- Diagnosis: One function (
high-traffic-function) has a very largeReservedConcurrency(e.g., 800), leaving little for others. - Fix: Re-evaluate the necessity of that high reserved concurrency. If the function can tolerate occasional throttling or if its peak usage is less than 800, reduce its
ReservedConcurrency.aws lambda put-function-concurrency --function-name high-traffic-function --reserved-concurrency 500. - Why it works: Similar to Cause 2, it releases capacity back into the shared pool.
- Diagnosis: One function (
-
Common Cause 4: Unexpected Spikes in Unreserved Functions.
- Diagnosis: Even with adequate account limits and reasonable reserved concurrency, sudden, unforecasted spikes in traffic to functions without reserved concurrency can exhaust the
AvailableUnreservedpool. - Fix: If these unreserved functions are critical, consider setting a modest
ReservedConcurrencyfor them to guarantee their capacity, or request an account concurrency limit increase if the overall demand warrants it. - Why it works: Explicitly reserving capacity for these functions prevents them from consuming the general pool, or a higher account limit allows for larger overall bursts.
- Diagnosis: Even with adequate account limits and reasonable reserved concurrency, sudden, unforecasted spikes in traffic to functions without reserved concurrency can exhaust the
-
Common Cause 5: Misunderstanding of Reserved Concurrency’s Impact.
- Diagnosis: Developers assume setting
ReservedConcurrencyfor Function A doesn’t affect Function B, when in reality, it reduces the shared pool available to Function B (and others). - Fix: Educate teams on how reserved concurrency consumes from the global account pool. Adjust settings collaboratively based on actual needs and account limits.
- Why it works: A shared understanding leads to better capacity planning and resource allocation.
- Diagnosis: Developers assume setting
-
Common Cause 6: Regional vs. Account Limits.
- Diagnosis: You might have high concurrency in
us-east-1andus-west-2separately, but if your total reserved concurrency across both regions, or the total actual executions across both regions, exceeds the sum of your account’s regional limits, you’ll see throttling. - Fix: Ensure your reserved concurrency is allocated appropriately per region and that your total account concurrency requests are spread across regions or that regional limits are increased individually.
- Why it works: Concurrency limits are per-region. You need to manage them within each region you operate in.
- Diagnosis: You might have high concurrency in
The next error you’ll hit after resolving these is likely a ProvisionedConcurrencySpilloverLimitExceeded if you’re using provisioned concurrency, or a ResourceNotFoundException if you’ve accidentally deleted a function while troubleshooting.