Back to Blog

AWS Lambda Beyond the Handler for the DVA-C02 Exam: Function URLs, Response Streaming, Destinations, Extensions, Custom Runtimes, Container Images, Code Signing & Recursive Loop Detection

A practitioner's deep dive into the Lambda features the DVA-C02 exam tests beyond versions and concurrency. Function URLs (AWS_IAM vs NONE, CORS, throttling, when to use API Gateway instead), response streaming and its 200 MB limit, asynchronous destinations vs dead-letter queues, external and internal extensions and the execution-environment lifecycle, custom runtimes on provided.al2023 and the Runtime API, container-image functions, code signing with AWS Signer, recursive loop detection, and the quotas that show up in questions.

By Sailor Team , October 16, 2026

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 $LATEST or 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 Invoke API 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.

AuthTypeWho can callWhat must exist
AWS_IAMOnly principals whose request is SigV4-signed and authorisedCaller 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
NONEAnyone with the URL, no authenticationA 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

NeedFunction URLAPI Gateway
AuthIAM or noneIAM, Lambda authorizers, Cognito user pools, OAuth 2.0 / JWT
Request validation, mapping templates, response cachingNoYes (REST)
Custom domain names, API keys and usage plans, WAF, private APIs, WebSockets, canary stagesNoYes
TimeoutFunction timeout, up to 15 minutes29-second default integration timeout
Response size6 MB buffered, 200 MB streamed10 MB payload
ThrottlingReserved concurrency onlyPer API, stage and method, with queuing
CostLambda pricing onlyPer-request API Gateway charge after the free tier
Best forWebhooks, single-function microservices, prototypes, long-running or streamed responsesProduction 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, the InvokeWithResponseStream API 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 InvokeWithResponseStream through 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
TriggerFailure onlyOn failure and/or on success (separate targets)
TargetsSQS standard queue or SNS standard topicSQS standard, SNS standard, Lambda function, EventBridge event bus, S3 bucket (on-failure only)
Payload deliveredThe original event only, plus RequestID, ErrorCode and ErrorMessage as message attributesA full invocation record: requestContext (condition such as RetriesExhausted or EventAgeExceeded, approximateInvokeCount), requestPayload, responseContext (status code, functionError), responsePayload
ScopeFunction level only; versions inherit $LATEST’s DLQFunction, version or alias
FIFO targetsNot supportedNot 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_OPTIONS to attach a Java agent). They cannot register for the SHUTDOWN event.

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

PhaseWhat happensLimits worth memorising
InitThree 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
InvokeLambda 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/nextThe function timeout bounds the whole phase including extension work. PostRuntimeExtensionsDuration measures the extra time extensions spend after the runtime
ShutdownLambda stops the runtime and sends SHUTDOWN (reason SPINDOWN, TIMEOUT or FAILURE) to external extensions0 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 predecessor provided.al2 was deprecated on July 31, 2026, along with the rest of the Amazon Linux 2 runtimes, so any current question about Go or Rust functions assumes provided.al2023. (Go 1.x as a managed runtime was retired in January 2024.)
  • The entry point is an executable file named bootstrap at the root of the deployment package or in a layer. If it is missing or not executable the function fails with Runtime.InvalidEntrypoint.
  • The runtime reads three environment variables: _HANDLER (the configured handler string), LAMBDA_TASK_ROOT (where your code lives) and AWS_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 and Lambda-Runtime-Trace-Id), invoke the handler, POST /runtime/invocation/{AwsRequestId}/response with the result or POST .../error on failure. Initialisation failures go to POST /runtime/init/error. Propagating the trace header into _X_AMZN_TRACE_ID is 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.

TopicContainer-image facts
SizeUp to 10 GB uncompressed (vs 50 MB zipped / 250 MB unzipped for .zip)
RegistryMust 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 imagesAWS 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 testingThe Runtime Interface Emulator (RIE) lets you curl the function on localhost:9000 as Lambda would
FormatsDocker image manifest V2 schema 2 or OCI; Linux only; single architecture per image (x86_64 or arm64, no multi-arch manifests)
FilesystemRead-only, except writable /tmp (512 MB to 10,240 MB); no USER directive needed, Lambda runs a least-privilege default user
LayersNot supported with container images; bake dependencies and extensions into the image
Runtime updatesYou rebuild and redeploy from the latest base image; AWS does not auto-patch container images and sends no deprecation notices for them
LifecycleAfter 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:

  1. AWS Signer – you create a signing profile and use it to sign the deployment artifact, producing a signed package.
  2. Code signing configuration (CSC) – a Lambda resource listing allowed signing profile ARNs and a policy. You attach a CSC to a function.
  3. 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, a SignatureValidationErrors CloudWatch 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 RecursiveInvocationException to the event source mapping, which keeps incrementing the message’s receive count until the source queue’s maxReceiveCount moves it to the queue’s own DLQ.
  • Notifications: the RecursiveInvocationsDropped metric (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: PutFunctionRecursionConfig with --recursive-loop Allow (default Terminate) for designs that intentionally recurse. With Allow, 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

ResourceQuota
Memory128 MB to 10,240 MB in 1 MB steps; 1,769 MB ≈ 1 vCPU; CPU scales with memory
Timeout900 seconds (15 minutes)
/tmp ephemeral storage512 MB to 10,240 MB
Environment variables4 KB total
Layers per function5
Deployment package50 MB zipped (direct upload), 250 MB unzipped including layers and custom runtime; container image 10 GB
Invocation payload6 MB sync request/response; 200 MB streamed response; 1 MB async
Streaming bandwidthUncapped for first 6 MB, then 2 MBps
Concurrency1,000 per Region default (new accounts lower), raisable; scaling 1,000 environments per 10 seconds per function
Extensions10 registered per function
Function URL rate10 × reserved concurrency RPS, 429 beyond
Resource-based policy20 KB
ENIs per VPC3,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

RequirementAnswer
Expose one function over HTTPS cheaply; webhook; prototypeFunction URL
Public function URL must never be created in the orgSCP denying CreateFunctionUrlConfig/UpdateFunctionUrlConfig unless lambda:FunctionUrlAuthType = AWS_IAM
CORS errors with duplicate Access-Control-Allow-OriginConfigure CORS on the URL, remove headers from code
Stop all traffic to a URL immediatelyReserved concurrency 0
OAuth / Cognito / usage plans / WAF / custom domainAPI Gateway
Response larger than 6 MB or slow time-to-first-byteResponse streaming (Node.js streamifyResponse, or custom runtime / Web Adapter), function URL RESPONSE_STREAM or InvokeWithResponseStream
Capture failed async events with the error responseOn-failure destination (SQS/SNS/Lambda/EventBridge/S3)
Capture failed async events, payload only, oldest optionDLQ (SQS or SNS standard)
Failed payloads near 1 MBS3 or SQS destination, not SNS (256 KB)
SQS-triggered function failingDLQ on the source queue (redrive policy), not the function
Ship logs/metrics to a third-party tool without changing codeExternal extension as a layer
Shutdown phase suddenly 2 s longExternal extension registered
Run Go/Rust/PHPprovided.al2023 + bootstrap
Runtime.InvalidEntrypointbootstrap missing or not executable
Dependencies > 250 MB; reuse Docker CIContainer 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 deploySigner profile + code signing config, Enforce
Audit unsigned deployments without blockingWarn + alarm on SignatureValidationErrors
Function writes to its own trigger queueRecursive 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 $LATEST or an alias, use AWS_IAM or NONE auth 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.al2023 and a bootstrap executable speaking the Runtime API; provided.al2 was 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.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now