AWS Lambda is the most heavily tested single service on the Developer Associate (DVA-C02) exam. The broad serverless guide gives you the map; this article is the deep dive into Lambda itself — the parts that show up as scenario questions where three answers look plausible and only one respects how the service actually runs your code. If you understand the execution environment lifecycle, versions and aliases, and the two kinds of concurrency, you’ll answer the majority of Lambda questions correctly and quickly.
This guide assumes you know what Lambda is. It focuses on the operational mechanics AWS tests. For where Lambda fits alongside the rest of the exam, see the DVA-C02 exam guide for 2026 and plan your prep with the DVA-C02 study plan. For how Lambda ties into messaging and orchestration, the event-driven applications guide is the companion piece; for packaging and deployment with SAM, see the AWS SAM guide.
The Execution Environment Lifecycle (Why Cold Starts Happen)
Everything about Lambda performance flows from one idea: your function runs inside a reusable execution environment — a micro-VM (Firecracker) that Lambda creates, freezes, thaws, and eventually destroys. Understanding its phases explains cold starts, the /tmp reuse trick, and why global-scope code matters.
There are three phases:
| Phase | What happens | When it runs |
|---|---|---|
| Init | Download code, start the runtime, run your handler file’s global/static code | On a cold start (new environment) |
| Invoke | Run your handler function for a single event | Every invocation |
| Shutdown | Environment is torn down | When Lambda reclaims idle capacity |
A cold start is any invocation that has to go through Init first — there’s no warm environment to reuse. A warm start reuses an existing frozen environment and skips Init entirely. That’s why code you put outside the handler (opening a database connection, creating an SDK client, loading a config) runs once per environment and is then reused across many invocations:
// Runs during INIT — once per execution environment, reused when warm
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const client = new DynamoDBClient({});
// Runs during INVOKE — every single event
exports.handler = async (event) => {
const result = await client.send(/* ... */);
return result;
};
Two exam-critical consequences:
- Reuse expensive setup in global scope, not inside the handler, to make warm invocations fast.
- Never rely on state persisting between invocations. The environment might be reused, but you cannot guarantee it — treat every invocation as potentially isolated. A common wrong answer is “store the counter in a global variable to persist across calls.” That’s not durable; use DynamoDB or another store.
Cold-start duration is driven by package size, runtime, and VPC attachment. To reduce cold starts predictably, you use provisioned concurrency (covered below).
Versions: Immutable Snapshots of Your Function
Every function has $LATEST — the mutable, editable draft. When you publish a version, Lambda takes an immutable snapshot of the code and the configuration at that moment and gives it a monotonically increasing number (1, 2, 3…). Published versions cannot be changed; that immutability is the point.
# Publish the current $LATEST as an immutable numbered version
aws lambda publish-version --function-name orders-api
# -> returns "Version": "3"
Each version gets its own ARN you can invoke directly:
arn:aws:lambda:us-east-1:111122223333:function:orders-api:3 # version 3
arn:aws:lambda:us-east-1:111122223333:function:orders-api # $LATEST
Because a version freezes configuration too, environment variables and memory settings are captured at publish time. If you change an environment variable, you must publish a new version for that change to appear in an immutable version.
Aliases: The Pointer You Actually Invoke
An alias is a named, mutable pointer to a version — think prod, staging, dev. Clients invoke the alias ARN, and you move the alias from version 2 to version 3 to “deploy” without changing anything on the caller side.
# Create an alias 'prod' pointing at version 3
aws lambda create-alias --function-name orders-api \
--name prod --function-version 3
# Later, promote version 4 by repointing the alias
aws lambda update-alias --function-name orders-api \
--name prod --function-version 4
The alias ARN callers use never changes:
arn:aws:lambda:us-east-1:111122223333:function:orders-api:prod
This is the standard pattern the exam expects: triggers, API Gateway integrations, and event source mappings point at an alias, never at $LATEST, so you get controlled, reversible deploys.
Weighted Aliases: Canary Deploys Built In
An alias can split traffic between two versions by weight — Lambda’s native canary/linear deployment primitive:
# Send 10% of traffic to version 4, 90% stays on version 3
aws lambda update-alias --function-name orders-api --name prod \
--function-version 3 \
--routing-config '{"AdditionalVersionWeights": {"4": 0.1}}'
Here the alias’s primary version is 3 and 10% shifts to version 4. Watch metrics, then increase the weight or roll back by removing it. This is exactly what CodeDeploy automates for canary/linear Lambda deployments — a frequent DVA-C02 scenario. Note the limit: a weighted alias splits across exactly two versions.
| Concept | Mutable? | What it is |
|---|---|---|
$LATEST | Yes | The editable draft |
| Version (1, 2, …) | No | Immutable code + config snapshot |
| Alias | Yes | Named pointer to a version (can weight two) |
Concurrency: The Two Kinds You Must Distinguish
Concurrency is the number of in-flight executions at one instant. By default all functions in a Region share an account concurrency limit (1,000 to start, raisable). The exam tests two managed forms, and mixing them up is a classic trap.
Reserved Concurrency
Reserved concurrency carves out a guaranteed slice of the account pool for one function, and simultaneously caps that function at that number.
- It guarantees the function can always scale up to the reserved amount.
- It limits the function to never exceed it (protecting downstream systems like an RDS database with limited connections).
- It subtracts from the pool available to all other functions.
- Setting reserved concurrency to 0 effectively disables the function (a fast kill switch).
aws lambda put-function-concurrency \
--function-name orders-api --reserved-concurrent-executions 50
Reserved concurrency does not cost extra and does not reduce cold starts — it’s about how many can run, not how fast they start.
Provisioned Concurrency
Provisioned concurrency keeps a set number of execution environments initialized and warm, ready to respond with no cold start.
- It eliminates cold starts for the provisioned count.
- It costs money while provisioned (you pay to keep environments warm).
- It’s applied to a version or alias, not
$LATEST. - You typically scale it with Application Auto Scaling on a schedule or metric.
aws lambda put-provisioned-concurrency-config \
--function-name orders-api --qualifier prod \
--provisioned-concurrent-executions 20
| Reserved concurrency | Provisioned concurrency | |
|---|---|---|
| Purpose | Guarantee & cap execution count | Eliminate cold starts |
| Cold starts | No effect | Removed for provisioned count |
| Cost | No extra charge | Charged while provisioned |
| Applied to | Function | Version or alias |
| Set to 0 | Disables the function | N/A |
When a question says “predictable low latency for a spiky, latency-sensitive API,” the answer is provisioned concurrency. When it says “stop this function from overwhelming the database” or “guarantee capacity for a critical function,” the answer is reserved concurrency.
Lambda Layers: Share Code and Dependencies
A layer is a .zip of libraries, a custom runtime, or shared code that you attach to functions. Instead of bundling the same dependencies into every deployment package, you publish them once as a layer and reference it.
- A function can use up to 5 layers.
- Layers are extracted into
/optin the execution environment. - The unzipped deployment package + all layers must stay within the 250 MB limit.
- Layers are versioned and immutable, just like functions.
aws lambda publish-layer-version --layer-name shared-utils \
--zip-file fileb://layer.zip \
--compatible-runtimes nodejs20.x
aws lambda update-function-configuration --function-name orders-api \
--layers arn:aws:lambda:us-east-1:111122223333:layer:shared-utils:2
Use layers to keep deployment packages small (faster uploads, and the console editor works when the function package itself is under the inline limit) and to share common code across many functions.
Environment Variables and Encryption
Environment variables let you externalize configuration from code. Key exam facts:
- They are encrypted at rest with a KMS key by default (an AWS-managed key, or a customer-managed key you choose).
- For values in transit / to avoid plaintext in the console, you can enable encryption helpers that encrypt the variable with a CMK and decrypt it in code at runtime.
- The total size of all environment variables is limited (4 KB).
- For secrets, the recommended pattern is to store them in Secrets Manager or SSM Parameter Store and fetch them at Init — not to hardcode secrets, even as env vars.
aws lambda update-function-configuration --function-name orders-api \
--environment "Variables={TABLE_NAME=orders,LOG_LEVEL=info}" \
--kms-key-arn arn:aws:kms:us-east-1:111122223333:key/abcd-1234
A frequent wrong answer is “put the database password in an environment variable.” It’s encrypted at rest, but the current best practice the exam rewards is Secrets Manager (with rotation) or Parameter Store SecureString, retrieved by the function.
/tmp Ephemeral Storage
Each execution environment has a writable /tmp directory, configurable from 512 MB up to 10 GB. It’s ephemeral but reused across warm invocations in the same environment, which makes it useful as a cache for downloaded files or as scratch space for processing.
aws lambda update-function-configuration --function-name image-proc \
--ephemeral-storage '{"Size": 2048}'
Because /tmp persists only within a single environment’s lifetime, treat it as a cache, never as durable storage. If you need shared or durable state, use S3, EFS (which Lambda can mount), or a database.
Event Source Mappings: Poll-Based Triggers
How Lambda is invoked splits into two models, and the DVA-C02 loves to probe the difference:
- Push (event) sources — S3, SNS, API Gateway — invoke Lambda directly by calling its
InvokeAPI. Invocation is asynchronous for S3/SNS and synchronous for API Gateway. - Poll-based sources — SQS, Kinesis Data Streams, DynamoDB Streams — use an event source mapping. Lambda itself polls the source, batches records, and invokes your function synchronously with the batch.
aws lambda create-event-source-mapping \
--function-name orders-processor \
--event-source-arn arn:aws:sqs:us-east-1:111122223333:orders-queue \
--batch-size 10
Key event-source-mapping knobs the exam tests: batch-size, maximum-batching-window, and error handling. For streams (Kinesis/DynamoDB), records are processed in order per shard, and a failing batch blocks the shard until it succeeds or expires — so you configure a bisect-on-error and an on-failure destination. For SQS, you use ReportBatchItemFailures to return only the failed message IDs so successful ones aren’t reprocessed.
Async Invocations, Retries, and Destinations
For asynchronous invocations (S3, SNS, EventBridge), Lambda queues the event internally and retries on function error — twice, with delays, by default. You control the outcome with:
- Destinations — route successful and failed async results to SQS, SNS, EventBridge, or another Lambda. Destinations carry richer context than a DLQ and are the modern recommendation.
- Dead-letter queue (DLQ) — an older mechanism sending failed events to an SQS queue or SNS topic after retries are exhausted.
aws lambda put-function-event-invoke-config --function-name orders-api \
--maximum-retry-attempts 1 \
--destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:us-east-1:111122223333:orders-dlq"}}'
Know that DLQ/destinations apply to asynchronous invocations; synchronous callers (API Gateway) get the error back directly and handle retries themselves.
Exam Gotchas Cheat Sheet
| Scenario | Correct answer |
|---|---|
| Reduce latency for a spiky, latency-sensitive function | Provisioned concurrency |
| Stop a function from overwhelming an RDS database | Reserved concurrency (cap) |
| Instantly disable a function | Reserved concurrency = 0 |
| Deploy safely with 10% canary traffic | Weighted alias / CodeDeploy canary |
| Share libraries across many functions | Lambda layers |
| Persist small state between invocations | External store (DynamoDB), not globals |
| Store DB credentials for a function | Secrets Manager / Parameter Store |
| Process SQS without reprocessing successes | ReportBatchItemFailures |
| Speed up warm invocations | Init clients in global scope |
Practice Against Realistic Questions
Lambda’s mechanics are easy to read and hard to recall under time pressure, because the wrong answers are designed to look right. The fix is repetition against exam-style scenarios that force you to distinguish reserved from provisioned concurrency, alias from version, and push from poll. Sailor.sh’s AWS Certified Developer Associate (DVA-C02) Mock Exam Bundle gives you full-length, timed practice exams with detailed explanations for every option — so by exam day you recognise the Lambda pattern in a scenario within seconds. Pair it with the monitoring and troubleshooting guide to round out the operational side of the exam.
Frequently Asked Questions
What’s the difference between reserved and provisioned concurrency?
Reserved concurrency guarantees and caps how many concurrent executions a function can have (and set to 0 disables it). Provisioned concurrency keeps a set number of environments warm to eliminate cold starts — it costs money and is applied to a version or alias. They solve different problems and can be used together.
Why should I point triggers at an alias instead of $LATEST?
Aliases give you controlled, reversible deploys: callers reference a stable alias ARN while you repoint it between immutable versions, and you can shift traffic gradually with weighted routing. Pointing at $LATEST means every code edit is live immediately with no rollback path.
How do I do a canary deployment with Lambda?
Publish a new version, then update your alias’s routing config so a small percentage (e.g. 10%) goes to the new version while the rest stays on the old one. Increase the weight as metrics stay healthy, or remove it to roll back. CodeDeploy automates this for you.
Does global-scope code run on every invocation?
No. Code outside your handler runs during the Init phase — once per execution environment — and is reused across warm invocations. Only the handler body runs on every invocation. That’s why you initialize SDK clients and connections globally.
Where should I store secrets for a Lambda function?
In AWS Secrets Manager or SSM Parameter Store (SecureString), retrieved at Init. Environment variables are encrypted at rest but are still the less-preferred place for credentials; Secrets Manager adds rotation and finer access control.
How many times does Lambda retry an asynchronous invocation?
By default, twice (three total attempts) with delays. You can tune this with the max retry attempts setting and route exhausted or successful events to a destination (SQS, SNS, EventBridge, or Lambda) or to a dead-letter queue.
Key Takeaways
- The execution environment lifecycle (Init → Invoke → Shutdown) explains cold starts and why you initialize clients in global scope.
- Versions are immutable snapshots; aliases are mutable pointers you invoke and can weight across two versions for canaries.
- Reserved concurrency guarantees and caps execution count (0 = disabled); provisioned concurrency keeps environments warm to kill cold starts.
- Layers share dependencies (max 5, extracted to
/opt, 250 MB unzipped limit). - Prefer Secrets Manager/Parameter Store over env vars for credentials;
/tmp(512 MB–10 GB) is a per-environment cache, not durable storage. - Poll-based sources use event source mappings with batch and ordering semantics; async sources retry and support destinations/DLQ.
Internalize these and Lambda shifts from the exam’s biggest risk to its biggest source of easy points. Then prove it with timed, explanation-rich practice until the patterns are automatic.