Most DVA-C02 Lambda questions live in two domains: Development with AWS Services (32%) and Troubleshooting and Optimization (18%). The ones candidates get right are about versions, aliases, concurrency and event source mappings. The ones they get wrong are about the features around the handler: how to expose a function over HTTP without API Gateway, how a response can exceed 6 MB, where a failed asynchronous event goes and what the record contains, what runs alongside your code in the execution environment, how to run a language Lambda doesn’t ship, how to package a function as a container, and how to stop an unsigned artifact or a runaway loop from deploying or running. Each is a short, well-defined mechanism, and each is a reliable source of one or two exam questions.
This guide assumes you already know the execution-environment lifecycle, cold starts, versions, aliases, reserved and provisioned concurrency, and layers. Those are taught in the Lambda versions, aliases and concurrency guide, while SnapStart and event source mappings each have their own deep dive. None of that is re-taught here. A naming note first: AWS’s documentation now calls the classic function model Lambda Event Functions, to distinguish it from newer Lambda compute shapes such as Web Functions, Managed Instances and MicroVMs. The exam, the CLI and this article all still say “Lambda function,” and everything below is about Event Functions.
1. Function URLs: HTTPS Without API Gateway
A function URL is a dedicated HTTPS endpoint attached directly to a function. Lambda generates it, it never changes, and it looks like this:
https://<url-id>.lambda-url.<region>.on.aws
Facts the exam tests:
- A URL attaches to
$LATESTor to an alias, never to a numbered version. Pointing the URL at an alias is how you get safe deployments (shift the alias, the URL follows). - Endpoints are dual-stack (IPv4 and IPv6) and reachable only from the public internet. Function URLs do not support PrivateLink or VPC-internal access; if a client inside a VPC needs to call Lambda privately, use the
InvokeAPI through an interface VPC endpoint. - Deleting a URL is irreversible; a new one gets a different
url-id.
Auth type: AWS_IAM vs NONE
Access is controlled by the URL’s AuthType combined with the function’s resource-based policy.
| AuthType | Who can call | What must exist |
|---|---|---|
AWS_IAM | Only principals whose request is SigV4-signed and authorised | Caller needs lambda:InvokeFunctionUrl and lambda:InvokeFunction (both are required for URLs created from October 2025 onward). Same account: identity policy or resource-based policy. Cross-account: both |
NONE | Anyone with the URL, no authentication | A resource-based policy granting lambda:InvokeFunctionUrl and lambda:InvokeFunction to * with the condition lambda:FunctionUrlAuthType = NONE. The console and AWS SAM create it for you; the CLI, CloudFormation and the API do not, and without it callers get 403 Forbidden even though auth is NONE |
Two condition keys matter: lambda:FunctionUrlAuthType (AWS_IAM or NONE) and lambda:InvokedViaFunctionUrl (restricts lambda:InvokeFunction to calls that arrive through the URL, so a public URL policy cannot be abused to invoke the function another way). The governance pattern is an SCP or IAM deny on lambda:CreateFunctionUrlConfig and lambda:UpdateFunctionUrlConfig with StringNotEquals lambda:FunctionUrlAuthType = AWS_IAM, which blocks anyone in the organisation from creating public URLs. IAM Access Analyzer also flags function URLs that grant public access.
# Create a URL on the prod alias, IAM-authenticated
aws lambda create-function-url-config \
--function-name orders-api \
--qualifier prod \
--auth-type AWS_IAM \
--cors '{"AllowOrigins":["https://app.example.com"],"AllowMethods":["GET","POST"]}'
CORS: configure it on the URL, not in the function
Lambda can inject Access-Control-Allow-Origin, -Methods, -Headers, -Expose-Headers, -Allow-Credentials and -Max-Age (default 5 seconds) for you. The precedence rule is a classic exam detail: for preflight OPTIONS requests, only the URL’s configured CORS headers are returned; for non-preflight requests, Lambda returns both the configured headers and any the function emitted, which produces the browser error “Access-Control-Allow-Origin contains multiple values.” AWS’s recommendation, and the exam answer, is to configure CORS on the URL and stop sending CORS headers from code.
Throttling and the emergency switch
Function URLs have no throttling settings of their own. You throttle with reserved concurrency: the maximum request rate is 10 × reserved concurrency requests per second, and anything beyond concurrency or RPS gets HTTP 429. Setting reserved concurrency to 0 rejects all traffic, which is how you “deactivate” a URL during an incident without deleting it.
Function URL vs API Gateway
| Need | Function URL | API Gateway |
|---|---|---|
| Auth | IAM or none | IAM, Lambda authorizers, Cognito user pools, OAuth 2.0 / JWT |
| Request validation, mapping templates, response caching | No | Yes (REST) |
| Custom domain names, API keys and usage plans, WAF, private APIs, WebSockets, canary stages | No | Yes |
| Timeout | Function timeout, up to 15 minutes | 29-second default integration timeout |
| Response size | 6 MB buffered, 200 MB streamed | 10 MB payload |
| Throttling | Reserved concurrency only | Per API, stage and method, with queuing |
| Cost | Lambda pricing only | Per-request API Gateway charge after the free tier |
| Best for | Webhooks, single-function microservices, prototypes, long-running or streamed responses | Production APIs with multiple routes, rich auth, transformation and governance |
When a scenario says “minimal cost,” “simplest way to expose one function,” “webhook receiver,” “needs to run for 5 minutes,” or “stream partial responses,” the answer is a function URL. When it says “OAuth,” “Cognito,” “usage plans,” “request validation,” “WAF” or “custom domain,” it is API Gateway. The API Gateway side is covered in the API Gateway integrations and authorizers guide.
2. Response Streaming: Breaking the 6 MB Barrier
By default Lambda buffers the whole response and returns it when the handler finishes, with a 6 MB synchronous payload limit. Response streaming sends bytes to the client as the function produces them, which improves time-to-first-byte for chatty UIs and model-generated text, and lifts the limit to 200 MB per response (a soft limit).
- Where it works: function URLs with
InvokeMode: RESPONSE_STREAM, theInvokeWithResponseStreamAPI through the SDK, and API Gateway proxy integrations configured for streamed transfer. The Lambda console always shows a buffered response, so “I tested in the console and nothing streamed” is expected behaviour, not a bug. - Which runtimes: natively the Node.js managed runtimes, where you wrap the handler with
awslambda.streamifyResponse()and write to a response stream object. For Python, Java and others you use a custom runtime that implements streaming over the Runtime API, or the Lambda Web Adapter. - Bandwidth: the first 6 MB of each response streams uncapped; after that Lambda caps the remainder at 2 MBps. If your responses never exceed 6 MB the cap never applies.
- Billing: you pay for the full function duration, and the function keeps running even if the client disconnects. Streaming functions with long timeouts deserve a hard look at cost.
- VPC caveat: function URLs cannot stream to clients inside a VPC. Inside a VPC, call
InvokeWithResponseStreamthrough an interface VPC endpoint for Lambda.
// Node.js: minimal streaming handler
export const handler = awslambda.streamifyResponse(
async (event, responseStream, context) => {
responseStream.setContentType("text/plain");
for (const chunk of await produceChunks(event)) {
responseStream.write(chunk);
}
responseStream.end();
}
);
Exam framing: “a function returns 50 MB reports to a browser and fails with a payload-too-large error” → response streaming over a function URL. “Users wait 20 seconds before seeing any output from a generative text endpoint” → response streaming to improve time-to-first-byte.
3. Asynchronous Destinations vs Dead-Letter Queues
Asynchronous invocations (S3 notifications, SNS, EventBridge, InvocationType=Event) are queued by Lambda and retried on function error twice by default (configurable 0–2) within a maximum event age (60 seconds to 6 hours). What happens to an event after that is where destinations and DLQs come in.
| Dead-letter queue (DLQ) | Destination | |
|---|---|---|
| Trigger | Failure only | On failure and/or on success (separate targets) |
| Targets | SQS standard queue or SNS standard topic | SQS standard, SNS standard, Lambda function, EventBridge event bus, S3 bucket (on-failure only) |
| Payload delivered | The original event only, plus RequestID, ErrorCode and ErrorMessage as message attributes | A full invocation record: requestContext (condition such as RetriesExhausted or EventAgeExceeded, approximateInvokeCount), requestPayload, responseContext (status code, functionError), responsePayload |
| Scope | Function level only; versions inherit $LATEST’s DLQ | Function, version or alias |
| FIFO targets | Not supported | Not supported (delivery fails and emits DestinationDeliveryFailures) |
Destinations are the newer, richer mechanism and the answer to “capture why events failed” or “route successful results onward without writing code.” The S3 on-failure destination stores one JSON object per failed event under aws/lambda/async/<function-name>/YYYY/MM/DD/..., which is the answer for “retain failed payloads larger than SNS’s 256 KB limit.” Required permissions live on the execution role (sqs:SendMessage, sns:Publish, s3:PutObject + s3:ListBucket, lambda:InvokeFunction, events:PutEvents); for KMS-encrypted S3 buckets add kms:GenerateDataKey. AWS recommends scoping s3:PutObject with s3:ResourceAccount so a deleted destination bucket cannot be re-created by someone else to capture your records.
aws lambda update-function-event-invoke-config \
--function-name orders-processor:prod \
--maximum-retry-attempts 1 \
--maximum-event-age-in-seconds 3600 \
--destination-config '{
"OnSuccess": {"Destination": "arn:aws:events:us-east-1:111122223333:event-bus/orders"},
"OnFailure": {"Destination": "arn:aws:sqs:us-east-1:111122223333:orders-failed"}
}'
Two interactions regularly appear in questions. Setting reserved concurrency to 0 on an async function sends new events straight to the DLQ or on-failure destination with no retries. And for SQS event sources, configure the DLQ on the source queue, not on the function: the function’s DLQ only serves Lambda’s internal async queue, and poll-based SQS invocations never enter it. Stream sources (Kinesis, DynamoDB) and Kafka have their own on-failure destinations configured on the event source mapping.
4. Extensions and the Execution-Environment Lifecycle
Extensions are programs that run inside the execution environment alongside your function, typically to ship logs, metrics and traces to an observability tool, fetch secrets and parameters, or enforce security policy. AWS provides several (the Parameters and Secrets Lambda Extension, CloudWatch Lambda Insights), partners ship many, and you can write your own.
External vs internal
- External extensions run as independent processes, can be written in any language (compiled binaries are recommended), start before the runtime, and keep running after the invocation completes so they can flush telemetry without delaying the response to the caller.
- Internal extensions run inside the runtime process as a thread, started through environment variables or wrapper scripts (for example
JAVA_TOOL_OPTIONSto attach a Java agent). They cannot register for theSHUTDOWNevent.
Deployment: for .zip functions an extension is a layer whose contents land in /opt/extensions/; for container-image functions you copy the extension binary into the image. Extension size counts toward the 250 MB unzipped limit, extensions share the function’s CPU, memory, /tmp and IAM role, and you are billed for their execution time in 1 ms increments.
The lifecycle, with extensions in it
| Phase | What happens | Limits worth memorising |
|---|---|---|
| Init | Three sub-phases in order: Extension init (each extension registers via POST /2020-01-01/extension/register with its file name in the Lambda-Extension-Name header and subscribes to INVOKE and/or SHUTDOWN), Runtime init, Function init (your static code) | Up to 10 extensions per function. Init time is billed and counts toward the timeout. With SnapStart, Init runs at version publish |
| Invoke | Lambda sends the event to the runtime and an INVOKE metadata event (request ID, deadline, ARN, tracing header) to subscribed extensions. The response goes back to the caller as soon as the runtime returns, even if extensions are still working. Every extension signals done via GET /extension/event/next | The function timeout bounds the whole phase including extension work. PostRuntimeExtensionsDuration measures the extra time extensions spend after the runtime |
| Shutdown | Lambda stops the runtime and sends SHUTDOWN (reason SPINDOWN, TIMEOUT or FAILURE) to external extensions | 0 ms with no extensions, 500 ms with an internal extension, 2,000 ms with external extensions; anything slower gets SIGKILL |
An extension that fails to initialise causes Lambda to restart the execution environment; extensions are treated as mission-critical. Extensions consume logs and metrics through the Telemetry API (the successor to the Logs API), which streams platform, function and extension telemetry to the extension’s own HTTP listener. The exam cares less about the HTTP details than about these facts: extensions run before and after your code, they are deployed as layers, they share your resources and role, and the Shutdown phase lengthens when they are present.
5. Custom Runtimes and the Runtime API
Lambda ships managed runtimes for Node.js, Python, Java, .NET and Ruby. For anything else (Go, Rust, PHP, C++, a language version AWS has not shipped), you use the OS-only runtime and bring your own runtime.
- The OS-only identifier is
provided.al2023(Amazon Linux 2023). Its predecessorprovided.al2was deprecated on July 31, 2026, along with the rest of the Amazon Linux 2 runtimes, so any current question about Go or Rust functions assumesprovided.al2023. (Go 1.x as a managed runtime was retired in January 2024.) - The entry point is an executable file named
bootstrapat the root of the deployment package or in a layer. If it is missing or not executable the function fails withRuntime.InvalidEntrypoint. - The runtime reads three environment variables:
_HANDLER(the configured handler string),LAMBDA_TASK_ROOT(where your code lives) andAWS_LAMBDA_RUNTIME_API(host:port of the Runtime API). - It then runs the processing loop against the Runtime API:
GET /runtime/invocation/next(a long poll that returns the event body plus headers such as the request ID andLambda-Runtime-Trace-Id), invoke the handler,POST /runtime/invocation/{AwsRequestId}/responsewith the result orPOST .../erroron failure. Initialisation failures go toPOST /runtime/init/error. Propagating the trace header into_X_AMZN_TRACE_IDis what keeps X-Ray segments linked.
#!/bin/sh
# bootstrap: minimal custom runtime loop
set -euo pipefail
while true; do
HEADERS="$(mktemp)"
EVENT=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
RESPONSE=$(./my-handler "$EVENT")
curl -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${REQUEST_ID}/response" -d "$RESPONSE"
done
For Go and Rust you rarely write this by hand: the official aws-lambda-go and aws-lambda-rust-runtime libraries implement the loop, and you compile a binary named bootstrap. A custom runtime can also implement response streaming by setting Lambda-Runtime-Function-Response-Mode: streaming and chunked transfer encoding on the response call, which is how non-Node.js languages stream.
Exam framing: “the team wants to run a compiled Rust binary” → provided.al2023 with a bootstrap executable. “Function on provided.al2 must be migrated before the deprecation blocks updates” → change the runtime to provided.al2023 and rebuild against AL2023 (newer glibc). “Runtime.InvalidEntrypoint” → missing or non-executable bootstrap.
6. Container-Image Functions
Lambda accepts two package types, .zip and container image, chosen at creation and not changeable afterwards.
| Topic | Container-image facts |
|---|---|
| Size | Up to 10 GB uncompressed (vs 50 MB zipped / 250 MB unzipped for .zip) |
| Registry | Must be in Amazon ECR in the same Region; cross-account repositories work when both the role’s identity policy and the ECR repository policy allow ecr:BatchGetImage and ecr:GetDownloadUrlForLayer |
| Base images | AWS base images (language runtime + Runtime Interface Client + Runtime Interface Emulator preinstalled), AWS OS-only provided images, or any image if you add the Runtime Interface Client yourself |
| Local testing | The Runtime Interface Emulator (RIE) lets you curl the function on localhost:9000 as Lambda would |
| Formats | Docker image manifest V2 schema 2 or OCI; Linux only; single architecture per image (x86_64 or arm64, no multi-arch manifests) |
| Filesystem | Read-only, except writable /tmp (512 MB to 10,240 MB); no USER directive needed, Lambda runs a least-privilege default user |
| Layers | Not supported with container images; bake dependencies and extensions into the image |
| Runtime updates | You rebuild and redeploy from the latest base image; AWS does not auto-patch container images and sends no deprecation notices for them |
| Lifecycle | After upload Lambda optimises the image: state Pending → Active. Unused for weeks → Inactive (first invoke fails while it re-optimises). Image deleted or permissions revoked → Failed |
The exam uses container images for three scenarios: dependencies that exceed 250 MB (ML libraries, large binaries), teams that already standardise on Docker tooling and CI, and “I need the same artifact to run locally and in Lambda.” The shared-responsibility twist (“who patches the base image?”) is the most common trap. Container images are also how ECS and EKS workloads are packaged, and the ECS, ECR and Fargate guide covers the registry side in depth.
7. Code Signing: Only Trusted Artifacts Deploy
Code signing guarantees that only code signed by a trusted publisher reaches a function. The pieces:
- AWS Signer – you create a signing profile and use it to sign the deployment artifact, producing a signed package.
- Code signing configuration (CSC) – a Lambda resource listing allowed signing profile ARNs and a policy. You attach a CSC to a function.
- At every deployment Lambda checks integrity (hash matches the signature), expiry (signature still valid), mismatch (signed by an allowed profile) and revocation (not revoked).
The policy, UntrustedArtifactOnDeployment, has two values:
Warn(default) – deployment is allowed, aSignatureValidationErrorsCloudWatch metric is emitted and the event is written to CloudTrail.Enforce– deployment is blocked, with the same metric and log.
Details the exam checks: the policy governs expiry, mismatch and revocation failures; an integrity failure always blocks. Checks run at deployment time only, so there is no runtime overhead. Adding a CSC to a function does not stop already-deployed unsigned code; it keeps running until the next deployment. Any layers added to a signed function must also be signed by an allowed profile. There is no additional charge for Signer or Lambda code signing. Current documentation states code signing applies to functions deployed as .zip or container image packages; older study material that says “zip only” is out of date.
aws lambda create-code-signing-config \
--allowed-publishers SigningProfileVersionArns=arn:aws:signer:us-east-1:111122223333:/signing-profiles/release/abc123 \
--code-signing-policies UntrustedArtifactOnDeployment=Enforce
aws lambda put-function-code-signing-config \
--function-name payments \
--code-signing-config-arn arn:aws:lambda:us-east-1:111122223333:code-signing-config:csc-0123456789abcdef
Scenario: “a regulated company must ensure only artifacts produced by its CI pipeline can be deployed to production functions, and unsigned deployments must fail” → Signer profile owned by the pipeline role, CSC with Enforce. “They want to audit first without breaking deployments” → Warn and alarm on SignatureValidationErrors.
8. Recursive Loop Detection
A function that writes to the same queue, topic or bucket that triggers it creates an infinite loop and an unbounded bill. Lambda’s recursive loop detection is on by default for every account, free, and needs no X-Ray active tracing (it piggybacks on X-Ray tracing headers that supported SDKs propagate).
- Supported in the loop: Amazon SQS, SNS, S3, EventBridge custom event buses, and Lambda-to-Lambda chains (sync or async). DynamoDB and other services are not detected, so a DynamoDB Streams → Lambda → DynamoDB loop will run unchecked.
- Threshold: when the same triggering event has caused about 16 invocations in one request chain, Lambda stops the next invocation in that chain. Other triggers on the function are unaffected.
- What happens to the event: it is sent to the function’s DLQ or on-failure destination if one is configured. For SQS sources Lambda returns
RecursiveInvocationExceptionto the event source mapping, which keeps incrementing the message’s receive count until the source queue’smaxReceiveCountmoves it to the queue’s own DLQ. - Notifications: the
RecursiveInvocationsDroppedmetric (emitted immediately), an AWS Health Dashboard entry and an email to the account contacts (both up to 3.5 hours later; one email per function per 24 hours). - Opt-out:
PutFunctionRecursionConfigwith--recursive-loop Allow(defaultTerminate) for designs that intentionally recurse. WithAllow, the metric is not emitted. - SDK requirement: the function must use an SDK version new enough to propagate the metadata (for example boto3 1.24.46+, JavaScript SDK v3 3.105.0+).
The exam framing is “a developer accidentally configured the output queue to be the input queue; what limits the blast radius and how do you recover?” Answer: Lambda terminates the loop after ~16 iterations and notifies you; you then set reserved concurrency to 0 or disable the event source mapping, fix the variable that points source and target at the same ARN, and drain the DLQ.
9. The Quotas That Show Up in Questions
| Resource | Quota |
|---|---|
| Memory | 128 MB to 10,240 MB in 1 MB steps; 1,769 MB ≈ 1 vCPU; CPU scales with memory |
| Timeout | 900 seconds (15 minutes) |
/tmp ephemeral storage | 512 MB to 10,240 MB |
| Environment variables | 4 KB total |
| Layers per function | 5 |
| Deployment package | 50 MB zipped (direct upload), 250 MB unzipped including layers and custom runtime; container image 10 GB |
| Invocation payload | 6 MB sync request/response; 200 MB streamed response; 1 MB async |
| Streaming bandwidth | Uncapped for first 6 MB, then 2 MBps |
| Concurrency | 1,000 per Region default (new accounts lower), raisable; scaling 1,000 environments per 10 seconds per function |
| Extensions | 10 registered per function |
| Function URL rate | 10 × reserved concurrency RPS, 429 beyond |
| Resource-based policy | 20 KB |
| ENIs per VPC | 3,000 (shared with EFS and others) |
When a question’s numbers do not fit these, the “fix” is usually to change approach: S3 for large inputs and presigned URLs for large outputs, response streaming for big synchronous responses, container images for big dependencies, EFS for big shared data, Step Functions for work longer than 15 minutes. The SDK, retries and presigned URLs guide covers the S3-handoff pattern, and the monitoring, troubleshooting and optimization guide covers the metrics referenced throughout this article.
Decision Cheat Sheet
| Requirement | Answer |
|---|---|
| Expose one function over HTTPS cheaply; webhook; prototype | Function URL |
| Public function URL must never be created in the org | SCP denying CreateFunctionUrlConfig/UpdateFunctionUrlConfig unless lambda:FunctionUrlAuthType = AWS_IAM |
CORS errors with duplicate Access-Control-Allow-Origin | Configure CORS on the URL, remove headers from code |
| Stop all traffic to a URL immediately | Reserved concurrency 0 |
| OAuth / Cognito / usage plans / WAF / custom domain | API Gateway |
| Response larger than 6 MB or slow time-to-first-byte | Response streaming (Node.js streamifyResponse, or custom runtime / Web Adapter), function URL RESPONSE_STREAM or InvokeWithResponseStream |
| Capture failed async events with the error response | On-failure destination (SQS/SNS/Lambda/EventBridge/S3) |
| Capture failed async events, payload only, oldest option | DLQ (SQS or SNS standard) |
| Failed payloads near 1 MB | S3 or SQS destination, not SNS (256 KB) |
| SQS-triggered function failing | DLQ on the source queue (redrive policy), not the function |
| Ship logs/metrics to a third-party tool without changing code | External extension as a layer |
| Shutdown phase suddenly 2 s long | External extension registered |
| Run Go/Rust/PHP | provided.al2023 + bootstrap |
Runtime.InvalidEntrypoint | bootstrap missing or not executable |
| Dependencies > 250 MB; reuse Docker CI | Container image (≤ 10 GB) in ECR, same Region |
| Who patches the base image of a container function? | You do; rebuild and redeploy |
| Only pipeline-signed code may deploy | Signer profile + code signing config, Enforce |
| Audit unsigned deployments without blocking | Warn + alarm on SignatureValidationErrors |
| Function writes to its own trigger queue | Recursive loop detection stops it at ~16 iterations; event goes to DLQ/destination |
Practice Against Realistic Scenarios
Every mechanism in this article is small enough to learn in an afternoon, but the exam tests them in combination: a function URL with NONE auth that returns 403 because CloudFormation did not add the resource policy; a streaming function whose bill is high because clients disconnect but the function runs on; a destination that silently fails because the target was a FIFO queue; a Rust function stuck on a deprecated runtime. Working through scenario questions that mix these details is the fastest way to find which ones you only think you know.
Sailor.sh’s AWS Certified Developer - Associate (DVA-C02) Mock Exam Bundle includes Lambda scenarios across function URLs, streaming, destinations, extensions, custom runtimes, container images and code signing, with explanations that spell out why each distractor fails. Use it alongside the DVA-C02 exam guide, the serverless development guide for the surrounding architecture, and the SAM deployments guide for wiring function URLs, destinations and code signing into templates.
Frequently Asked Questions
When should I use a Lambda function URL instead of API Gateway?
Use a function URL when you need a simple, low-cost HTTPS endpoint for a single function: webhooks, prototypes, internal tools, or endpoints that need the full 15-minute Lambda timeout or response streaming. Use API Gateway when you need Cognito or OAuth authentication, Lambda authorizers, custom domains, request validation and transformation, caching, usage plans and API keys, WAF integration, WebSockets or private APIs.
Why does my function URL with auth type NONE return 403?
Because auth type NONE still requires a resource-based policy that grants lambda:InvokeFunctionUrl and lambda:InvokeFunction to everyone with the condition lambda:FunctionUrlAuthType = NONE. The console and AWS SAM add that policy automatically; the CLI, CloudFormation and the Lambda API do not, so you must add it with add-permission.
What is the maximum response size with Lambda response streaming?
Up to 200 MB per streamed response (a soft limit), compared with 6 MB for buffered synchronous responses. The first 6 MB stream with uncapped bandwidth; the remainder is capped at 2 MBps. Streaming works through function URLs, the InvokeWithResponseStream API and API Gateway proxy integrations, and natively only on Node.js managed runtimes; other languages use a custom runtime or the Lambda Web Adapter.
What is the difference between a Lambda destination and a dead-letter queue?
A dead-letter queue (SQS or SNS standard) receives only the original event when all retries fail, and is configured at the function level. A destination can fire on success or on failure, supports SQS, SNS, Lambda, EventBridge and (on failure) S3, delivers a full invocation record including the request payload, the response or error and the failure condition, and can be configured per version or alias. Destinations are the recommended option for new designs.
What is a Lambda extension and how is it deployed?
An extension is a program that runs in the function’s execution environment to integrate with monitoring, security or configuration tools. External extensions run as separate processes (any language) that start before the runtime and can continue after the invocation finishes; internal extensions run inside the runtime process. For .zip functions extensions are deployed as layers under /opt/extensions/; for container images they are copied into the image. A function can register up to 10 extensions.
How do I run a language Lambda does not support natively?
Choose the provided.al2023 OS-only runtime and include an executable named bootstrap in your deployment package or a layer. The bootstrap implements the Runtime API loop: fetch the next event from /runtime/invocation/next, run the handler, and post the result to /runtime/invocation/<id>/response or the error endpoint. Go and Rust have official libraries that implement this for you. provided.al2 was deprecated on July 31, 2026.
Can Lambda container images use layers?
No. Layers apply only to .zip deployment packages. For container images you add dependencies and extensions directly to the image. Images can be up to 10 GB uncompressed, must live in Amazon ECR in the same Region as the function, must target a single architecture, and must be rebuilt by you to pick up base-image security patches.
What does Lambda code signing check and what happens on failure?
At deployment time Lambda verifies the artifact’s integrity, that the signature has not expired, that it was signed by an allowed AWS Signer profile, and that it has not been revoked. An integrity failure always blocks deployment. For the other three checks, the code signing configuration’s policy decides: Warn allows the deployment and emits the SignatureValidationErrors metric and a CloudTrail record, while Enforce blocks it. Existing unsigned code keeps running until the next deployment, and layers must also be signed.
How does Lambda recursive loop detection work?
Lambda tracks events flowing between a function and SQS, SNS, S3, EventBridge custom buses and other Lambda functions using metadata propagated by supported SDKs. When the same triggering event has caused roughly 16 invocations in a chain, Lambda stops the next invocation, sends the event to the function’s DLQ or on-failure destination if configured, emits the RecursiveInvocationsDropped metric and notifies you via the Health Dashboard and email. You can allow intentional recursion with PutFunctionRecursionConfig. Loops through DynamoDB or other unsupported services are not detected.
Key Takeaways
- Function URLs map to
$LATESTor an alias, useAWS_IAMorNONEauth backed by a resource-based policy (which CLI/CloudFormation users must add themselves), configure CORS on the URL, and throttle via reserved concurrency at 10 RPS per unit. - Response streaming lifts the response limit from 6 MB to 200 MB and improves time-to-first-byte; native on Node.js, bandwidth-capped at 2 MBps after 6 MB, billed for full duration even if the client leaves.
- Destinations beat DLQs: on-success and on-failure, more targets including S3, a full invocation record, and per-version or alias scope. For SQS triggers, the DLQ belongs on the source queue.
- Extensions run as layers before and after your code, share your resources and role, add a 500 ms or 2,000 ms Shutdown phase, and are capped at 10 per function.
- Custom runtimes use
provided.al2023and abootstrapexecutable speaking the Runtime API;provided.al2was deprecated on July 31, 2026. - Container images go to 10 GB in same-Region ECR, cannot use layers, are single-architecture, and are patched by you, not AWS.
- Code signing with AWS Signer blocks or warns on untrusted deployments at deploy time with no runtime cost; integrity failures always block.
- Recursive loop detection is on by default for SQS, SNS, S3, EventBridge custom buses and Lambda chains, terminates after ~16 iterations and routes the event to your DLQ or destination.