15.2
Lambda Limits, Concurrency and Cold Starts
Execution limits, reserved and provisioned concurrency, throttling and retries, cold starts and SnapStart.
26 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Recite the Lambda limits that change a design (memory 128 MB to 10,240 MB, timeout 15 minutes, 6 MB synchronous and 1 MB asynchronous payload, 50 MB zipped / 250 MB unzipped package, 10 GB container image, /tmp 512 MB to 10,240 MB, 4 KB of environment variables, 5 layers) and the standard way round each one.
- Explain why CPU comes with memory (one vCPU at 1,769 MB, up to six at 10,240 MB) and why a bigger function can cost the same and run faster.
- Calculate the concurrency a workload needs (requests per second × average duration in seconds), and check it against the account quota, the 10 requests per second per unit rule and the scaling rate of 1,000 new execution environments every 10 seconds per function.
- Predict what happens to a throttled invocation: 429 for synchronous callers, up to 6 hours of retries and then a destination or DLQ for asynchronous events, the message staying in the queue for SQS.
- Use reserved concurrency as a guarantee, a cap that protects a downstream database, and a kill switch (0), and know that 100 units always stay unreserved.
- Explain cold starts (Init, Invoke, Shutdown), shrink them, and choose between provisioned concurrency (with Application Auto Scaling) and SnapStart, including SnapStart’s uniqueness and network-connection caveats.
#Why limits and concurrency matter
Lesson 15.1 sold Lambda as “no servers to manage, scales on its own, pay per request”. All true, but Lambda scales inside a fence. A function may run for at most 15 minutes, accept at most 6 MB from a synchronous caller, and the whole account shares one pool of concurrent executions. Most production incidents with Lambda are not bugs in the code: they are a function hitting one of these fences, or one function eating the pool that another one needed.
This lesson covers the fences (the limits), the pool (concurrency, reserved concurrency, throttling) and the delay of starting new copies (cold starts, provisioned concurrency, SnapStart). The exam asks about all three, usually as a scenario: “payments are throttled during a marketing campaign”, “the first request after deployment is slow”, “a Java function takes seconds to start”.
#The limits that shape a Lambda design
All quotas are per Region (per account). The ones in the first block can never be raised; concurrency can.
| Limit | Value | Can it be raised? | What you do when you hit it |
|---|---|---|---|
| Memory | 128 MB to 10,240 MB, in 1 MB steps | No | Split the work, or move to Fargate / EC2 |
| Timeout | 900 seconds (15 minutes) per invocation | No | Step Functions to split the job (lesson 15.7), or Fargate (lesson 14.2) |
| Synchronous payload | 6 MB request and 6 MB response (200 MB for a streamed response) | No | Upload to S3 with a presigned URL and pass the key |
| Asynchronous payload | 1 MB per event (256 KB until 2025) | No | Put the data in S3, send a pointer |
| Environment variables | 4 KB in total | No | Parameter Store or Secrets Manager (chapter 21) |
| .zip package | 50 MB zipped for a direct upload, 250 MB unzipped including layers | No | Container image, or download big files into /tmp during init |
| Container image | 10 GB uncompressed | No | Fargate for anything bigger |
| Layers | 5 per function | No | Merge layers or use a container image |
| /tmp (ephemeral storage) | 512 MB default, up to 10,240 MB | No | EFS or S3 for shared or permanent data |
| File descriptors, processes and threads | 1,024 each | No | Close what you open; fewer threads |
| Code storage for .zip functions and layers | 300 GB per Region | No | Delete old versions, or store code in your own S3 bucket |
| Concurrent executions | 1,000 per account per Region | Yes, to tens of thousands | Request an increase in Service Quotas, or use reserved concurrency to share it fairly |
| Scaling rate | 1,000 new execution environments every 10 seconds, per function | No | Provisioned concurrency for known spikes; buffer with SQS |
Three of these numbers trip people up:
- Synchronous vs asynchronous payload. API Gateway accepts a 10 MB body, but the Lambda behind it accepts only 6 MB. For uploads the answer is always the same: the client puts the file straight into S3 (lesson 10.1, presigned URL) and Lambda gets only the bucket and key. The asynchronous limit was raised from 256 KB to 1 MB in 2025; older questions and slides still say 256 KB.
- The 15-minute timeout. It is per invocation. Longer work is either split into steps (a Step Functions Map state calls the function once per item) or does not belong in Lambda at all.
- Package size. The 250 MB unzipped limit includes all layers. A container image raises this to 10 GB. Large files that are only data (a model, a font set) can also be downloaded into /tmp during init, which survives as long as the execution environment is reused.
#Memory buys CPU
Lambda has no CPU setting. You choose memory, and Lambda gives CPU (and network bandwidth) in proportion: at 1,769 MB a function has the equivalent of one full vCPU, and at 10,240 MB up to six vCPUs. At 128 MB it gets a small slice of one.
So “the function uses only 90 MB, give it 128 MB” is often a false saving. Price is per GB-second: if doubling the memory halves the duration, the cost stays the same and the user waits half as long. Past the point where the code can use the extra CPU (a single-threaded program cannot use six vCPUs), more memory only costs more. Measure a few sizes (the open-source AWS Lambda Power Tuning tool does it for you) and pick the knee of the curve.
When a Lambda limit decides the design
A Dhaka e-commerce shop runs its product-photo backend on Lambda. Four everyday requests hit four hard limits: the 6 MB synchronous payload, the 15-minute timeout, the 250 MB unzipped package, and CPU that comes only with memory. Each one has a standard way round it.
Scenario
Synchronous payloads stop at 6 MB: send big files to S3 and pass only the key.
A seller uploads an 8 MB product video through the API. API Gateway accepts bodies up to 10 MB, so it passes the request on.
#Concurrency: how many at once
Concurrency is the number of requests a function is handling at the same moment. Each in-flight request occupies one execution environment (a small Firecracker microVM with your code loaded). One environment handles one request at a time; when it finishes, it can take the next one. If a new request arrives and every environment is busy, Lambda creates another one, up to the limits.
The rule of thumb from the AWS documentation:
Concurrency = average requests per second × average duration in seconds
- 100 requests per second, 0.5 s each → 50 concurrent executions.
- 400 requests per second, 0.25 s each → 100.
- 2,000 requests per second, 3 s each → 6,000: far above the default 1,000, so most requests would be throttled until the quota is raised.
Notice what moves the result: duration counts as much as traffic. If the database behind a function slows from 100 ms to 1 s, the same traffic needs ten times the concurrency. Many “Lambda throttled us” incidents start with a slow downstream, not a traffic spike.
#Two more ceilings: requests per second and scaling speed
- 10 requests per second per unit of concurrency (synchronous). Lambda limits each execution environment to 10 invocations per second, so very short functions hit this before they hit concurrency. A 20 ms function at 5,000 requests per second needs only 5,000 × 0.02 = 100 concurrency by the formula, but 100 units allow only 1,000 requests per second: it actually needs 500.
- Scaling rate. Each function can add up to 1,000 execution environments every 10 seconds (since November 2023; before that there was an account-wide burst of 500 to 3,000 followed by 500 per minute, which older material still quotes). AWS does not publish a time for a given level, but from that rate you can estimate it: zero to 5,000 concurrent takes somewhere around 40 to 50 seconds (the first 1,000 are available at once, and AWS refills the rate continuously rather than in steps), and requests above the current level are throttled meanwhile. Every one of those new environments is also a cold start.
Lambda publishes the metrics you need in CloudWatch (chapter 19): ConcurrentExecutions, Throttles, Duration, Invocations, and for provisioned concurrency ProvisionedConcurrencyUtilization.
Concurrency and throttling calculator
The wallet’s pay-merchant function on Eid eve. Choose the traffic, how long one request takes, the account limit, an optional reserved concurrency, and how much the other functions in the account are already using. Then calculate who gets throttled.
Requests per second
Average duration
Account concurrency limit
Reserved concurrency for this function
Concurrency other functions are using
Press “Calculate” to see the result.
#Throttling: what happens when concurrency runs out
When a request needs a new execution environment and the function may not have one (the account pool is empty, or the function is at its reserved concurrency), Lambda throttles it. What happens next depends entirely on how the function was invoked (invocation types, lesson 15.1).
#Synchronous: 429 straight back to the caller
API Gateway, an ALB, a function URL, Cognito triggers or your own SDK call wait for the answer. A throttle is returned at once as HTTP 429 (TooManyRequestsException, “Rate Exceeded”). Lambda stores nothing: the caller must retry, ideally with exponential backoff and jitter (the AWS SDKs do it for throttles automatically). Through API Gateway the user sees a 429 or 5xx error page. Retries only smooth short spikes; steady overload needs more concurrency.
#Asynchronous: Lambda retries for you, for up to 6 hours
S3 events, SNS, EventBridge and --invocation-type Event calls are handed to Lambda’s internal queue, and the caller gets 202 Accepted immediately. If the attempt is throttled (429) or hits a system error (5xx), Lambda puts the event back and tries again, with gaps that grow from 1 second to at most 5 minutes, for up to 6 hours by default (the maximum event age, configurable from 60 seconds to 6 hours).
A function error (an exception or a timeout in your code) is different: Lambda retries it twice by default (after about 1 minute, then about 2 more), and you can set 0, 1 or 2 retries. An event that runs out of retries or of age goes to the on-failure destination (SQS, SNS, EventBridge, another Lambda function or S3, with the error details) or the older dead-letter queue (SQS or SNS, the event only). Without either, it is dropped silently.
#Event source mappings: the queue is the buffer
For SQS, Kinesis, DynamoDB Streams, MSK and MQ, Lambda’s own pollers read the source and invoke the function synchronously with a batch. When that invoke is throttled, the poller simply backs off:
- SQS: the messages are not deleted; they become visible again after the visibility timeout and are read again. Set the visibility timeout to at least 6 times the function timeout. A message that keeps failing past the queue’s
maxReceiveCountgoes to the queue’s own DLQ (lesson 13.2), which is configured on the queue, not on the function. - Kinesis and DynamoDB Streams: the shard waits and retries the same batch until it succeeds or the record expires, so a throttled function delays everything behind it in that shard (lesson 13.5).
To cap how many copies one SQS queue may start, use the event source mapping’s maximum concurrency (2 to 1,000) rather than reserved concurrency alone: with maximum concurrency the poller stops reading instead of invoking and being throttled, so messages are not pushed towards the DLQ by throttles. Keep the function’s reserved concurrency at least as high as the total maximum concurrency of its queues.
Throttled: what happens to the request?
When a function has no concurrency left, Lambda does not queue a synchronous call for you. What happens next depends on how the function was invoked: synchronously, asynchronously, or by an event source mapping that polls a queue.
Scenario
The caller gets the error at once and must retry itself.
The app calls the balance function synchronously and waits for the answer, as API Gateway, an ALB or the SDK do.
#One pool for the whole account
The 1,000 concurrent executions belong to the account in that Region, not to each function. By default every function draws from the same unreserved pool, first come, first served.
#The noisy neighbour
That is the concurrency issue the slides warn about. Suppose a function behind an ALB gets many users and scales to 1,000. Now a function behind API Gateway with few users, and a script calling a third function through the SDK, both get 429, although they barely ran at all. One function’s burst starves all the others: a marketing campaign can take down payments, a runaway retry loop can take down the login.
#Reserved concurrency: a guarantee and a cap
Reserved concurrency sets aside a number of concurrent executions for one function:
- Guarantee (floor): no other function can use those units. If pay-merchant has 300 reserved, it can always run 300 copies, whatever the campaign does.
- Cap (ceiling): the function can never use more than its reservation, even when the rest of the pool sits idle. The slides write it as “reserved concurrency (= limit)”; it is both.
- Cost: free.
- Side effect: the reservation leaves the shared pool even when the function is idle. With 300 reserved, every other function shares 700.
- Rule: Lambda always keeps 100 units unreserved for functions without a reservation. With a 1,000 quota you can reserve at most 900 in total across all functions.
The cap side is just as useful as the guarantee:
- Protect a fragile downstream. A function that opens one database connection per copy, writing to a database that accepts 100 connections, can be capped at, say, 50. (For many functions sharing a database, RDS Proxy is the better tool, lesson 15.3.)
- Kill switch. Reserved concurrency 0 throttles every new invocation of the function at once, without deleting or redeploying anything. Running invocations finish; remove the setting to switch it back on.
- Cost control: a cap limits how much a bug or an attack can spend.
If one function needs more than the account allows, no reservation helps: request a quota increase (the slides: “open a support ticket”; today the Service Quotas console).
One concurrency pool for the whole account
A bKash-style wallet runs three functions in one account and Region: payments, a cashback campaign and a nightly report. By default they all draw from the same 1,000 concurrent executions. Watch what one runaway function does to the others, and how reserved concurrency stops it.
Scenario
Three functions share 1,000 concurrent executions on demand.
Concurrency in use (account limit 1,000)
| pay-merchant | cashback-promo | nightly-report | free in pool |
|---|---|---|---|
| 120 | 40 | 0 | 840 |
Concurrency is the number of requests a function is handling at the same moment; each one occupies an execution environment. The default quota is 1,000 per account per Region, for all functions together.
#Cold starts
#The execution environment lifecycle
Every execution environment goes through three phases:
- Init: Lambda creates the microVM, downloads your code, starts the runtime (Node.js, Python, Java…) and runs your code outside the handler once: imports, reading configuration, creating SDK clients and database connections. On demand, the Init phase may take at most 10 seconds.
- Invoke: the handler runs for the request. After it returns, the environment is frozen and kept for reuse; the next request to it skips Init entirely (a warm start).
- Shutdown: an environment that stays idle for a while is removed; Lambda also recycles environments every few hours even under load.
A cold start is a request that has to wait for Init. It happens to the first request to every new environment: after a deployment, after a quiet period, and for every extra concurrent request during a spike. Overall, cold starts hit under 1% of invocations, but they cluster at the worst moments (the start of a spike) and they show up in p99 latency rather than the average.
What makes Init slow, roughly from most to least common: a big package and many dependencies, a heavy framework (Spring Boot on Java, large .NET apps), creating many clients or connections, downloading files, and the language itself (Java and .NET start slower than Node.js and Python). Since August 2025, Lambda bills the Init phase for all function types, so a slow init now costs money as well as latency.
#Making cold starts shorter
- Put expensive setup outside the handler (clients, connections, config): it runs once per environment, not once per request. Never keep data there that must survive; environments disappear.
- Trim the package: only the dependencies you use, tree-shaking, lighter frameworks.
- More memory also speeds Init, because CPU comes with memory.
- Lambda in a VPC used to add seconds for creating an ENI. Since 2019, VPC functions use shared Hyperplane ENIs created when the function is configured, so the VPC no longer adds a noticeable cold start (lesson 15.3). Older material still says “avoid VPC because of cold starts”.
- When that is not enough: provisioned concurrency or SnapStart, below.
Cold start, warm start
A newspaper’s “latest headlines” function, invoked through API Gateway. The first request to a new execution environment pays for creating it and running the init code; later requests reuse it.
Scenario
New environment: download code, start the runtime, run init, then the handler.
The first request of the morning arrives. No execution environment exists for this function, or all of them are busy.
#Provisioned concurrency
Provisioned concurrency keeps a chosen number of execution environments initialized in advance, so requests that land on them never wait for Init (double-digit millisecond responses).
- It is set on a published version or an alias, never on
$LATEST. Callers must invoke that alias or version, or they do not use it. - Lambda runs the init code when it allocates the environments (it takes a minute or two) and again when it recycles them, so the code outside the handler should do as much as possible.
- Spillover: requests beyond the provisioned number use normal on-demand environments, with normal cold starts, from the unreserved pool (or from the function’s reserved concurrency). They are not throttled unless that pool is empty too.
- It counts against the account’s concurrency like a reservation: you can provision at most the unreserved quota minus 100, and if the function also has reserved concurrency, provisioned ≤ reserved.
- It costs money while configured, busy or idle: a charge per GB-second for the provisioned environments (US East: about $0.0000041667 per GB-second) plus a lower duration price when they run ($0.0000097222 per GB-second instead of $0.0000166667). Example: 100 environments of 2 GB for one hour = 100 × 2 × 3,600 = 720,000 GB-seconds ≈ $3.00 per hour before any request.
- Application Auto Scaling manages the number (register the alias as a scalable target): scheduled scaling for known peaks (raise it 15 minutes before the office rush, lower it after) and target tracking on
ProvisionedConcurrencyUtilization(for example 0.7) for gradual changes. Target tracking reacts in minutes, so sudden spikes still spill over meanwhile. The AWS docs suggest provisioning about 10% above the usual peak.
Reserved concurrencyProvisioned concurrency
- A number of concurrent executions set aside for one function: guaranteed to it, and its ceiling.
- Environments are still created on demand: cold starts still happen.
- Protects against noisy neighbours; caps a function to protect a downstream; 0 = kill switch.
- Set on the function (all versions together).
- Free.
- A number of pre-initialized environments, ready before any request.
- Removes cold starts for requests up to that number; beyond it, spillover to on-demand.
- Solves latency, not starvation (though it does consume pool units).
- Set on a version or alias, not
$LATEST; scheduled or target-tracking scaling with Application Auto Scaling. - Paid for every second it is configured.
Provisioned concurrency: warm before the first request
A Pathao-style ride app’s fare quote API must answer in under 100 ms. Provisioned concurrency keeps a set number of environments initialized on a published version or alias; Application Auto Scaling can change that number on a schedule or by utilization.
Scenario
Init runs before traffic arrives, so no request waits for it.
The team publishes version 7, points the alias live at it and sets provisioned concurrency 2 on the alias. It works only on a version or an alias, never on the unpublished version. After a minute or two, Lambda has created two environments and run their init code.
#SnapStart
SnapStart attacks the other side of the problem: instead of keeping environments warm, it makes starting a new one fast. When you publish a version with SnapStart on, Lambda runs Init once, takes a Firecracker snapshot of the initialized memory and disk, encrypts it and caches several copies. New environments for that version are restored from the snapshot instead of running Init again, often in well under a second instead of several seconds.
- Runtimes: Java 11 and later, Python 3.12 and later, .NET 8 and later (managed runtimes and their base images). Not Node.js, Ruby or OS-only runtimes.
- Price: no extra charge for Java. For Python and .NET you pay for caching the snapshot (per GB-second, minimum 3 hours, for as long as the version is active) and for each restore. The slides say “no extra cost for Java, Python and .NET”; only Java is free.
- Only on published versions (and aliases pointing to them), not
$LATEST. - Not compatible with provisioned concurrency, EFS, or /tmp larger than 512 MB.
Two caveats appear in exam questions and in real outages:
- Uniqueness. Everything created during Init is copied into every restored environment. A random seed, a unique ID or a secret generated in Init would be the same in all copies. Generate them after the restore: in the handler, or in an after-restore runtime hook (the
afterRestorehook on Java,@register_after_restoreon Python). - Network connections. A connection opened during Init, at publish time, may be long dead when the snapshot is restored hours later; Lambda does not guarantee its state. Validate and reopen connections after restore. Connections the AWS SDK creates usually recover by themselves. Temporary credentials and cached timestamps fetched in Init should be refreshed too.
SnapStart: init once, restore many times
A Java (Spring Boot) payment-status function takes 6 seconds to initialize. With SnapStart, Lambda runs the init when you publish a version, saves a snapshot of the initialized memory and disk, and resumes new environments from it.
Scenario
The slow init happens at publish time, not on a customer’s request.
SnapStart is switched on for published versions (Java 11+, Python 3.12+, .NET 8+). The developer publishes version 12.
#Which cold-start fix?
| Situation | Best fit | Why |
|---|---|---|
| Java, Python or .NET function with a slow Init, spiky traffic | SnapStart | Faster starts for every new environment, no always-on cost (free on Java) |
| Strict latency for every request, predictable peaks, any runtime | Provisioned concurrency with scheduled scaling | No Init at all on the provisioned environments |
| Node.js function with a slow start | Provisioned concurrency (SnapStart does not support Node.js), plus a smaller package | |
| Background or asynchronous processing | Usually nothing | Nobody waits for a few hundred extra milliseconds |
| Cold start caused by heavy code in the handler | Move the setup outside the handler | Runs once per environment |
#What goes wrong
| Symptom | Likely cause | Fix |
|---|---|---|
| API returns 429 / 5xx during a campaign, other functions are idle-looking | Another function took the account pool | Reserved concurrency on critical functions; quota increase |
| A function is throttled although the account has spare concurrency | Its own reserved concurrency is the cap | Raise or remove the reservation |
| Throttles right at the start of a sudden spike, then fine | Scaling rate (1,000 per 10 s) or cold starts | Provisioned concurrency before known spikes; buffer with SQS |
| Throttles on a very fast function with low concurrency | 10 requests per second per unit of concurrency | Raise concurrency (reserved or quota) |
| Asynchronous events disappear | No on-failure destination or DLQ; event older than the maximum event age | Configure a destination; alarm on DeadLetterErrors / AsyncEventsDropped |
| SQS messages land in the DLQ although the code is fine | Throttling consumed receives; visibility timeout too short | ESM maximum concurrency; visibility timeout ≥ 6 × function timeout; higher maxReceiveCount |
| “Task timed out after 900.00 seconds” | Work longer than 15 minutes | Step Functions, or Fargate |
RequestEntityTooLargeException | Payload over 6 MB (sync) or 1 MB (async) | Presigned S3 upload; pass a key |
| Database refuses connections when traffic rises | Each copy opens its own connection | Reserved concurrency as a cap; RDS Proxy (lesson 15.3) |
| Cold starts despite provisioned concurrency | Callers invoke $LATEST; or spillover beyond the provisioned number | Point the trigger at the alias; raise provisioned concurrency or use target tracking |
| Provisioned concurrency bill with almost no traffic | Configured 24/7 | Scheduled scaling; minimum capacity low at night |
| Duplicate IDs or the same “random” numbers after enabling SnapStart | Uniqueness created in Init | Generate after restore (handler or after-restore hook) |
| First query after a SnapStart restore fails | Connection opened in Init is stale | Reconnect after restore |
| A CPU-heavy function is slow at 128 MB | CPU comes with memory | Raise memory; measure cost per request |
#Lambda concurrency in system design
- Size it with the formula, then add headroom. Peak requests per second × p95 duration, plus room for a slower downstream. Compare with the account quota, and request increases weeks before a launch, not on the day.
- Separate critical paths. Reserve concurrency for payments, login and order capture; leave campaigns and batch jobs in the shared pool. For hard isolation, use separate accounts (each has its own quota, chapter 20).
- Protect what is behind Lambda. Lambda scales faster than databases and third-party APIs. Cap it with reserved concurrency or ESM maximum concurrency, put SQS in front to absorb bursts (lesson 13.1), and use RDS Proxy for relational databases.
- Prefer asynchronous where nobody is waiting. An S3 or SQS-driven function survives throttling (retries, buffers); a synchronous API turns throttling straight into user errors.
- Latency budget. User-facing and spiky: provisioned concurrency for the peak, or SnapStart for Java/Python/.NET. Background: accept cold starts.
- Throttling at the front door. API Gateway has its own throttling (10,000 requests per second per account by default, usage plans per client, lesson 15.6); throttling there is cheaper and friendlier than letting Lambda throw 429s.
#Try it yourself
Reserve concurrency, throttle a function on purpose, then add provisioned concurrency to an alias and scale it on a schedule. Output is shortened; the function fare-quote-example already exists.
REGION=ap-southeast-1
FN=fare-quote-example
# 1. Account quota and what is left unreserved
aws lambda get-account-settings --region $REGION \
--query '{limit:AccountLimit.ConcurrentExecutions,unreserved:AccountLimit.UnreservedConcurrentExecutions}'
# { "limit": 1000, "unreserved": 1000 }
# 2. Memory (and so CPU), timeout and /tmp size
aws lambda update-function-configuration --function-name $FN \
--memory-size 1769 --timeout 30 --ephemeral-storage '{"Size": 1024}'
# "MemorySize": 1769, "Timeout": 30, "EphemeralStorage": { "Size": 1024 }
# 3. Reserve 300 for this function: a guarantee and a cap
aws lambda put-function-concurrency --function-name $FN --reserved-concurrent-executions 300
# { "ReservedConcurrentExecutions": 300 }
aws lambda get-account-settings --query 'AccountLimit.UnreservedConcurrentExecutions'
# 700
# 4. Kill switch: 0 throttles every new invocation
aws lambda put-function-concurrency --function-name $FN --reserved-concurrent-executions 0
aws lambda invoke --function-name $FN --payload '{}' --cli-binary-format raw-in-base64-out out.json
# An error occurred (TooManyRequestsException) when calling the Invoke operation (reached max retries: 2): Rate Exceeded.
aws lambda delete-function-concurrency --function-name $FN # back to the shared pool
# 5. Asynchronous invocation: 202, with retries and a failure destination
aws lambda put-function-event-invoke-config --function-name $FN \
--maximum-retry-attempts 1 --maximum-event-age-in-seconds 3600 \
--destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:ap-southeast-1:111122223333:fare-failures-example"}}'
aws lambda invoke --function-name $FN --invocation-type Event --payload '{"from":"Gulshan"}' \
--cli-binary-format raw-in-base64-out out.json
# { "StatusCode": 202 }
# 6. Publish a version, point the alias live at it, provision 20 warm environments
aws lambda publish-version --function-name $FN --query Version
# "7"
aws lambda create-alias --function-name $FN --name live --function-version 7
aws lambda put-provisioned-concurrency-config --function-name $FN --qualifier live \
--provisioned-concurrent-executions 20
# { "RequestedProvisionedConcurrentExecutions": 20, "AllocatedProvisionedConcurrentExecutions": 0, "Status": "IN_PROGRESS" }
aws lambda get-provisioned-concurrency-config --function-name $FN --qualifier live --query Status
# "READY" (after a minute or two)
# 7. Let Application Auto Scaling manage it: 200 for the weekday rush, back to 20 after
aws application-autoscaling register-scalable-target --service-namespace lambda \
--resource-id function:$FN:live --scalable-dimension lambda:function:ProvisionedConcurrency \
--min-capacity 20 --max-capacity 300
aws application-autoscaling put-scheduled-action --service-namespace lambda \
--resource-id function:$FN:live --scalable-dimension lambda:function:ProvisionedConcurrency \
--scheduled-action-name morning-rush --schedule "cron(45 1 ? * SUN-THU *)" \
--scalable-target-action MinCapacity=200,MaxCapacity=300
# (01:45 UTC = 7:45 in Dhaka; a second action lowers MinCapacity to 20 at 10:30)
# 8. Or track utilization at 70%
aws application-autoscaling put-scaling-policy --service-namespace lambda \
--resource-id function:$FN:live --scalable-dimension lambda:function:ProvisionedConcurrency \
--policy-name pc-70 --policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{"TargetValue":0.7,"PredefinedMetricSpecification":{"PredefinedMetricType":"LambdaProvisionedConcurrencyUtilization"}}'
# 9. SnapStart on a Java or Python function (applies to versions published afterwards)
aws lambda update-function-configuration --function-name payment-status-example \
--snap-start ApplyOn=PublishedVersions
aws lambda publish-version --function-name payment-status-example \
--query '{v:Version,snap:SnapStart.OptimizationStatus}'
# { "v": "12", "snap": "On" }
# 10. Clean up the paid part
aws lambda delete-provisioned-concurrency-config --function-name $FN --qualifier live
Then look at the Throttles and ConcurrentExecutions metrics of the function in CloudWatch while you invoke it in a loop with reserved concurrency set to 1: the throttle count rises as soon as two invocations overlap.
#Summary
Key takeaways
- Hard limits (per Region): memory 128 MB–10,240 MB, timeout 15 min, payload 6 MB sync / 1 MB async (256 KB before 2025), package 50 MB zipped / 250 MB unzipped (layers included), container image 10 GB, /tmp 512 MB–10 GB, env vars 4 KB, 5 layers. Workarounds: S3 + presigned URL, Step Functions or Fargate, container images, /tmp or EFS.
- CPU comes with memory: 1 vCPU at 1,769 MB, up to 6 at 10,240 MB. More memory can be faster for the same price.
- Concurrency = requests per second × duration (s). Default quota 1,000 per account per Region, shared by all functions, raisable. Also: 10 requests per second per unit, and scaling of 1,000 environments per 10 s per function.
- Throttling: synchronous → 429, client retries; asynchronous → Lambda retries up to 6 h (1 s to 5 min backoff), then on-failure destination / DLQ or dropped; function errors get 2 retries; SQS → messages stay in the queue, DLQ on the queue; ESM maximum concurrency to cap a queue.
- Reserved concurrency: free; guarantee and cap for one function; protects against noisy neighbours, limits load on a database, 0 = kill switch; 100 units always stay unreserved.
- Cold start: Init (new environment + code outside the handler, max 10 s, billed since August 2025) before the first request of each environment. Put setup outside the handler, trim the package, add memory.
- Provisioned concurrency: pre-initialized environments on a version or alias; no cold start up to that number, spillover beyond; paid while configured; Application Auto Scaling (scheduled, target tracking); ≤ reserved concurrency.
- SnapStart: snapshot after Init at publish time, restore instead of init; Java 11+, Python 3.12+, .NET 8+; free for Java only; not with provisioned concurrency, EFS or /tmp > 512 MB; regenerate unique values and reconnect after restore.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
What is the maximum time a single Lambda invocation can run?
Self-checkQuestion
How does a Lambda function get more CPU power?
Self-checkQuestion
What is the default concurrent execution quota for Lambda?
Self-checkQuestion
An API receives 400 requests per second and each invocation takes 250 ms on average. How much concurrency does the function need?
Self-checkQuestion
A function in an account with the default quota receives 2,000 requests per second, and each request takes 3 seconds because it calls a slow partner API. What happens, and what is the first fix to consider?
Self-checkQuestion
A function takes 20 ms per request and must serve 5,000 synchronous requests per second. The formula gives 100 concurrency. Why is 100 not enough, and what is needed?
Self-checkQuestion
A payment function behind API Gateway is throttled while a marketing function in the same account bursts. The payment function must always be able to run up to 300 concurrent executions. What should you do?
Self-checkQuestion
What happens when a function synchronously invoked through API Gateway is throttled?
Self-checkQuestion
S3 invokes a function for every uploaded file. During a spike the function is throttled. What does Lambda do with those events by default?
Self-checkQuestion
An asynchronous function throws an exception for a malformed file. With default settings, how many times is the event attempted in total, and where does it go afterwards if nothing is configured?
Self-checkQuestion
Which two configurations keep failed asynchronous events instead of losing them?
Choose 2
Self-checkQuestion
An SQS queue triggers a function that has reserved concurrency 10. During peaks, messages that never failed in the code end up in the queue’s DLQ. What are the best two changes?
Choose 2
Self-checkQuestion
A nightly report function opens one connection per invocation to an RDS database that accepts 100 connections. When the schedule fires for 5,000 merchants, the database crashes. What is the simplest way to stop this?
Self-checkQuestion
A bug in a promotion function is paying customers too much. You need to stop all new invocations immediately without deleting or redeploying the function. What do you do?
Self-checkQuestion
The account quota is 1,000. Function A already has 600 reserved. What is the most you can reserve for function B?
Self-checkQuestion
Which two statements about reserved concurrency are true?
Choose 2
Self-checkQuestion
A user-facing API built with Node.js has slow first requests every morning and during the 8 a.m. rush. Latency must be consistent. What is the best solution?
Self-checkQuestion
Provisioned concurrency of 50 is configured on the alias prod, but CloudWatch still shows cold starts on almost every burst while the provisioned concurrency utilization metric stays at 0. What is the most likely cause?
Self-checkQuestion
A function with provisioned concurrency 20 and no reserved concurrency receives 30 concurrent requests. What happens to the 10 extra?
Self-checkQuestion
100 environments of 2 GB are kept as provisioned concurrency for 10 hours a day for 30 days. At $0.0000041667 per GB-second, roughly what does the provisioned part cost, before any requests or duration?
Self-checkQuestion
A Java Spring Boot function takes 6 seconds to initialize. The team wants faster starts during unpredictable spikes without paying for idle warm environments. What should they use?
Self-checkQuestion
After enabling SnapStart, a function that creates order IDs from a random generator seeded in its init code starts producing duplicate IDs during spikes. Why?
Self-checkQuestion
Which two statements about SnapStart are correct today?
Choose 2
Self-checkQuestion
A SnapStart function opens a connection to its own database server in the init code. The first query after some restores fails with a connection reset. What is the right fix?
Self-checkQuestion
Where should a function create its DynamoDB client and read its configuration to keep warm requests fast?
Self-checkQuestion
Which two events cause a cold start?
Choose 2
Self-checkQuestion
A seller app uploads 8 MB product videos through API Gateway to a Lambda function and gets errors. What is the recommended design?
Self-checkQuestion
A team adds a 1.2 GB machine-learning model to its function and the .zip deployment fails. Which two approaches work?
Choose 2
Self-checkQuestion
A traffic spike goes from zero to 5,000 concurrent requests in one second for a single function, in an account with a quota of 10,000. Roughly how long until the function can serve them all, and what happens meanwhile?
Self-checkQuestion
According to the slides, SnapStart improves performance “at no extra cost for Java, Python and .NET”. Which statement is accurate today?
Self-checkQuestion
Which statement about Lambda in a VPC and cold starts is correct today?
Self-checkQuestion
An S3-triggered thumbnail function must not be overwhelmed and must not lose events, but delays of a few minutes are fine. Which design is the most robust?