AWS Lambda Provisioned Concurrency: When It's Worth the Cost
Understand AWS Lambda provisioned concurrency pricing, how it eliminates cold starts, and the specific use cases where it justifies the cost over SnapStart or code optimization.
Your Lambda function handles user-facing requests, and the p99 latency is unacceptable. You have already trimmed the package, moved initialization outside the handler, and you know the problem is cold starts on infrequent or bursty traffic. The AWS documentation suggests provisioned concurrency. Before you enable it, you should understand precisely what you are paying for and whether cheaper solutions apply to your case.
What Provisioned Concurrency Is
When Lambda has no warm execution environment for a function, it initializes one from scratch — runtime boot, package load, initialization code. This is the cold start.
Provisioned Concurrency keeps a set number of execution environments pre-initialized and permanently warm. Requests that land on a provisioned environment experience no cold start. The initialization has already happened; the handler runs immediately.
You specify provisioned concurrency as a count on a specific function version or alias. Lambda maintains exactly that many initialized environments at all times, regardless of whether they are receiving invocations.
The Cost Model
Provisioned concurrency has two billing dimensions:
-
Provisioned Concurrency-Hours: You pay for the concurrency you provision, for every hour it is provisioned, whether or not it handles any invocations. This is the baseline cost that exists even at zero traffic.
-
Invocation duration at a discounted rate: Invocations served by provisioned environments are billed at a lower GB-second rate than on-demand Lambda invocations (roughly 60% of the on-demand price).
The net effect: provisioned concurrency adds a fixed floor cost in exchange for eliminating cold starts and reducing per-invocation compute cost. The economics favor provisioned concurrency when:
- The function receives enough invocations that the discounted invocation rate offsets the idle provisioning cost
- Or the latency requirement is strict enough that the cost is justified regardless of invocation volume
When Provisioned Concurrency Is Worth It
User-Facing APIs with Strict Latency SLAs
If your function is on the critical path of a user interaction — authentication, payment initiation, initial page API — and your SLA defines p99 latency requirements, cold starts are an unacceptable variance. A cold start that adds 500ms-2 seconds to a user-facing request is a product problem, not just an infrastructure metric.
In these cases, provisioned concurrency eliminates the problem entirely, and the cost is justified by the user experience and SLA requirement.
Predictable Traffic Spikes
If your traffic pattern is forecastable — business hours for a B2B SaaS, morning rush for a consumer app, known promotional events — you can schedule provisioned concurrency to be active during high-traffic periods and scaled back during quiet periods.
Use Application Auto Scaling with a scheduled scaling policy:
aws application-autoscaling put-scheduled-action \
--service-namespace lambda \
--resource-id function:my-function:prod \
--scheduled-action-name scale-up-morning \
--schedule "cron(0 8 * * ? *)" \
--scalable-target-action MinCapacity=50,MaxCapacity=50
This approach reduces the idle cost significantly. If you provision concurrency for 12 hours per day instead of 24, you cut the provisioning cost in half.
Functions Where Cold Starts Are Frequent
High cold start frequency compounds the user experience impact. A function that receives one invocation per minute will cold-start on almost every invocation — Lambda recycles execution environments after roughly 5-15 minutes of inactivity. Provisioned concurrency changes the economics at low invocation rates by ensuring warm environments persist.
For functions with very low invocation rates, the question becomes: does the improved experience justify the cost of provisioning concurrency for a function that runs rarely? Often the answer is no — a periodic keep-warm invocation (a scheduled EventBridge rule that pings the function every few minutes) is a simpler, near-zero-cost alternative.
When Provisioned Concurrency Is Not Worth It
When SnapStart Applies
If your function runs on a supported Java runtime, SnapStart reduces cold start duration by 80-90% with no idle cost. Test SnapStart before considering provisioned concurrency. For most Java Lambda use cases, SnapStart is the right tool.
When Code Optimization Has Not Been Applied First
Provisioned concurrency is expensive. Code optimization is free. Before provisioning concurrency:
- Hoist all client initialization to module scope
- Reduce package size with a bundler
- Choose a fast runtime (Node.js or Python if you have flexibility)
- Profile your initialization code and remove unnecessary work from the cold path
A function that cold-starts in 150ms after optimization may not need provisioned concurrency even for user-facing workloads.
When Traffic Is Sparse and Unpredictable
If your function is invoked irregularly — a few times per day, at unpredictable times — provisioned concurrency runs idle most of the time. The cost is continuous regardless of traffic. A background job, an admin tool, or an infrequently triggered webhook handler is a poor fit for provisioned concurrency unless the cold start latency is genuinely problematic for that use case.
When You Have Not Measured the Problem
Cold start latency is reported in CloudWatch Logs in the REPORT line as Init Duration. Before provisioning concurrency, verify:
- What percentage of your invocations are cold starts
- What the actual cold start duration is in milliseconds
- What the p99 latency is for your function, including cold and warm invocations
Sometimes the cold start problem is smaller than assumed. Sometimes the problem is in the handler logic rather than initialization. Measure before spending.
Sizing Provisioned Concurrency
Provisioned concurrency should be sized to match your expected peak concurrency, not average concurrency. If your function handles 200 concurrent requests at peak, provisioning 50 means 150 requests still land on cold-started environments during the peak.
Use CloudWatch metrics to find your actual peak concurrency:
ConcurrentExecutions— current concurrent invocationsProvisionedConcurrencySpilloverInvocations— invocations that did not hit a provisioned environment (you want this near zero)
Size provisioned concurrency to keep spillover invocations near zero during your target traffic windows.
Auto-Scaling Provisioned Concurrency
Application Auto Scaling supports target tracking for provisioned concurrency based on ProvisionedConcurrencyUtilization. Setting a target utilization of 70% means Auto Scaling will add provisioned concurrency when more than 70% of provisioned environments are in use, giving headroom before requests spill to cold starts.
Combine target tracking with scheduled actions to handle both gradual scaling and known traffic patterns.
Provisioned concurrency is not a default setting — it is a specific tool for a specific problem: user-facing, latency-sensitive Lambda functions where cold start elimination justifies the idle cost. For everything else, exhaust the free optimizations first.
If you are designing a Lambda architecture and need help making the right call on concurrency configuration, talk to Clixo. We build production serverless systems that are both fast and cost-efficient.