Prev Next

Cloud / AWS Lambda Interview questions

Last updated

1. What is AWS Lambda? 2. What is a Lambda function? 3. What is the purpose of a Lambda execution role? 4. What are the supported runtimes in AWS Lambda? 5. What is a Lambda handler function? 6. What are Lambda layers? 7. How do you deploy a Lambda function? 8. What is the purpose of the Lambda deployment package? 9. What are Lambda environment variables? 10. Define cold start in AWS Lambda? 11. What is the maximum execution timeout for a Lambda function? 12. Describe the event source mapping in Lambda? 13. What are the types of Lambda invocation models? 14. List the triggers that can invoke a Lambda function? 15. What is the purpose of the AWS Lambda context object? 16. How do you set memory allocation for a Lambda function? 17. What is Lambda@Edge? 18. What is the purpose of a dead-letter queue in Lambda? 19. Why do we use provisioned concurrency in Lambda? 20. How does Lambda handle concurrency limits? 21. What is the difference between concurrency and parallelism in Lambda? 22. How does Lambda scale to handle multiple requests? 23. When should you use synchronous vs asynchronous invocation? 24. What is the difference between Lambda and EC2 for compute? 25. How do you use VPC with a Lambda function? 26. Why does a Lambda function in a VPC take longer to start? 27. How is Lambda function versioning managed? 28. What is the difference between Lambda aliases and versions? 29. How do you troubleshoot a Lambda timeout error? 30. When would you choose Step Functions over chaining Lambdas directly? 31. What is the difference between reserved concurrency and provisioned concurrency? 32. How does Lambda retry failed asynchronous invocations? 33. Why should you keep Lambda functions stateless? 34. How do you optimize Lambda cold start times? 35. What happens when a Lambda function exceeds its memory limit? 36. Explain the execution flow of a Lambda function from invocation to response? 37. Explain the internal working of the Lambda execution environment lifecycle? 38. How can you optimize Lambda function performance for high-throughput workloads? 39. What is the difference between Lambda SnapStart and provisioned concurrency? 40. How does Lambda achieve isolation between concurrent executions? 41. Explain the lifecycle of a Lambda execution context? 42. How do you implement idempotency in Lambda functions? 43. Why doesn't increasing memory always reduce Lambda cost? 44. How does Lambda integrate with API Gateway for RESTful APIs? 45. What is the difference between Lambda's event-driven model and a traditional server model? 46. How do you secure secrets used by a Lambda function? 47. Explain how Lambda handles partial batch failures with SQS? 48. How can you monitor and debug Lambda functions in production? 49. What is the difference between Lambda extensions and Lambda layers? 50. How does Lambda pricing work with the free tier and billing model?

1. What is AWS Lambda?

AWS Lambda is a serverless, event-driven compute service that runs your code in response to triggers without you having to provision or manage servers.

You upload a function's code, Lambda handles the underlying compute, patching, and capacity, and it runs your code only when a matching event occurs, such as an API call, a file upload to S3, or a new message on a queue.

Billing is based on the number of requests and the compute time consumed, measured in GB-seconds, so you pay only while your code is actually executing.

Because there is no idle server to maintain, Lambda is widely used for APIs, data processing pipelines, automation scripts, and glue logic between AWS services.

Take quiz
AWS Lambda pricing is primarily based on:
Number of EC2 instances reserved
Requests and compute time (GB-seconds)
Total storage allocated to the function
Number of IAM roles attached
What must you manage yourself when using Lambda?
The underlying server OS and patching
Your function code and its configuration
The physical data center hardware
The hypervisor running your function

2. What is a Lambda function?

A Lambda function is the deployable unit of code that AWS Lambda executes - it packages your handler code, any dependencies, and a set of configuration settings (memory, timeout, runtime, IAM role) into one resource.

Each function is identified by a name and ARN, and it exposes a single handler method that Lambda calls with the incoming event whenever the function is invoked.

Functions can be packaged as a .zip archive uploaded directly, or as a container image pushed to Amazon ECR, which is useful when dependencies are large or you already have a Docker-based build pipeline.

Configuration (memory, environment variables, VPC settings) is versioned separately from code, letting you update either independently.

Take quiz
A Lambda function bundles together:
Only the raw source code with no config
Handler code plus configuration like memory and IAM role
A permanently running virtual machine
A static website hosted on S3
Besides a .zip archive, a Lambda function can be packaged as:
A container image stored in Amazon ECR
A CloudFormation stack export
An EBS snapshot
A Route 53 hosted zone

3. What is the purpose of a Lambda execution role?

The execution role is an IAM role that Lambda assumes on your function's behalf while it runs, and it determines which AWS services and resources the function is allowed to call.

For example, a function that reads from DynamoDB and writes to S3 needs an execution role with policies granting dynamodb:GetItem and s3:PutObject permissions; without them, those calls fail with an AccessDenied error at runtime, not at deployment time.

This role is separate from the resource-based policy attached to the function itself, which controls who is allowed to *invoke* the function (for example, allowing API Gateway or S3 to trigger it).

Best practice is to scope the execution role to the minimum permissions the function actually needs rather than reusing a broad, shared role.

Take quiz
The Lambda execution role controls:
Which users can view the function's source code
What AWS resources the function's code can access at runtime
How long the function can run
Which region the function is deployed in
Which policy type controls who can invoke a Lambda function?
The execution role's trust policy
A resource-based (permissions) policy on the function
The account's billing policy
The VPC's network ACL

4. What are the supported runtimes in AWS Lambda?

Lambda provides managed runtimes for several popular languages, each maintained by AWS with periodic security patches: Node.js, Python, Java, .NET (C#/PowerShell), Ruby, and Amazon's own Amazon Linux-based provided.al2023 runtime.

Languages without a first-party managed runtime - such as Go, Rust, or Kotlin - can run through a custom runtime built on provided.al2/provided.al2023, which implements the Lambda Runtime API yourself or via a community bootstrap.

Every runtime is also available through container images, letting you bring any base image (including ones with OS-level dependencies) as long as it implements the Lambda Runtime Interface Client.

Managed Runtime Latest Family Example
Node.js Node.js 20.x / 22.x
Python Python 3.12 / 3.13
Java Java 17 / 21
.NET .NET 8

Take quiz
A language with no AWS-managed Lambda runtime, like Go, can still run via:
A custom runtime on provided.al2023
Only by rewriting it in Python
Lambda@Edge exclusively
AWS Batch instead of Lambda
Container image support in Lambda mainly benefits functions that:
Never need any dependencies
Have large or OS-specific dependencies
Only run for under 1 second
Cannot use IAM roles

5. What is a Lambda handler function?

The handler is the specific method in your code that Lambda invokes to start execution - it's the entry point you configure as filename.method_name (or the equivalent for your runtime).

Lambda calls it with two main arguments: the event, a JSON-like object describing what triggered the invocation, and the context, which carries runtime information such as the remaining execution time.

def lambda_handler(event, context):
    name = event.get("name", "world")
    return {"statusCode": 200, "body": f"Hello, {name}"}

Whatever the handler returns becomes the function's output for a synchronous invocation, and any unhandled exception it raises is recorded as a function error in CloudWatch.

Take quiz
The Lambda handler receives which two arguments?
request and response
event and context
input and output
session and payload
What determines the return value seen by a synchronous caller?
Whatever value the handler function returns
The last line printed to stdout
The function's memory setting
The execution role's ARN

6. What are Lambda layers?

A layer is a .zip archive containing libraries, custom runtimes, or other dependencies that can be attached to one or more functions, so shared code doesn't have to be bundled into every deployment package.

Lambda extracts each attached layer into the /opt directory of the execution environment in the order they're listed, and a function can use up to five layers at once.

Layers are commonly used to ship a Python virtual environment, a set of Node.js modules, monitoring agents, or the AWS Lambda Powertools utility library, keeping the function's own deployment package small and focused on business logic.

Each layer is versioned independently, so you can update a shared dependency without touching every function that consumes it - you just point the function at the new layer version.

Take quiz
Where does Lambda extract a layer's contents at runtime?
/tmp
/opt
/var/task
/home
How many layers can a single Lambda function use at once?
Up to 2
Up to 5
Up to 20
Unlimited

7. How do you deploy a Lambda function?

The simplest path is uploading a .zip package or pointing to a container image in ECR through the Lambda console or the aws lambda create-function/update-function-code CLI commands.

For repeatable, production deployments, most teams use Infrastructure-as-Code: AWS SAM or the Serverless Framework for Lambda-focused apps, or the AWS CDK/CloudFormation when Lambda is one part of a larger stack.

  1. Package code and dependencies (zip or container image).
  2. Push the artifact (S3 for zips, ECR for images).
  3. Create or update the function resource with the new code reference.
  4. Publish a version and optionally shift an alias to it.

CI/CD pipelines (CodePipeline, GitHub Actions, Jenkins) typically automate these steps, running tests before promoting a new version to a "prod" alias.

Take quiz
Container-image-based Lambda functions are pushed to:
Amazon S3 only
Amazon ECR
AWS Secrets Manager
Amazon CloudFront
Which tool is purpose-built for defining serverless (Lambda) applications as code?
AWS SAM
Amazon Route 53
AWS Config
Amazon Cognito

8. What is the purpose of the Lambda deployment package?

The deployment package is the artifact that contains your function's compiled or interpreted code plus any third-party libraries it needs, and it's what Lambda actually deploys and runs.

For a .zip package uploaded directly through the API or console, the limit is 50 MB compressed and 250 MB uncompressed (including layers); uploading via S3 instead of directly raises the compressed limit to 250 MB as well.

Container images support up to 10 GB, which is why teams with heavy dependencies (ML libraries, native binaries) often switch to the container image packaging model.

Keeping the package lean matters beyond just staying under the limit - a smaller package downloads and initializes faster, which directly reduces cold-start latency.

Take quiz
The uncompressed size limit for a .zip-based Lambda deployment package is:
10 MB
50 MB
250 MB
1 GB
Container image-based Lambda functions can be as large as:
50 MB
250 MB
1 GB
10 GB

9. What are Lambda environment variables?

Environment variables are key-value pairs you attach to a function's configuration and read at runtime through the standard environment-variable APIs of your language, such as process.env.MY_VAR in Node.js or os.environ["MY_VAR"] in Python.

They're the standard way to pass configuration - database endpoints, feature flags, log levels - without hardcoding values into the code, so the same package can run in dev, staging, and prod with different settings.

By default they're encrypted at rest using an AWS-managed KMS key; you can instead supply your own customer-managed key for stricter control, and Lambda also supports encrypting specific values in transit via helper SDK calls.

They are not meant for large payloads - the combined size of all environment variables for a function is capped at 4 KB.

Take quiz
The total size limit for a Lambda function's environment variables is:
4 KB
40 KB
4 MB
No limit
By default, Lambda environment variables at rest are:
Stored in plain text with no protection
Encrypted using an AWS-managed KMS key
Only available to Lambda@Edge
Deleted after each invocation

10. Define cold start in AWS Lambda?

A cold start is the extra latency incurred the first time (or after a period of inactivity) a request hits a function and Lambda must create a brand-new execution environment before it can run your code.

That setup includes downloading the deployment package, starting the runtime, and running any code outside the handler (SDK client creation, static initializers) - only after that does the actual handler invocation begin.

Subsequent requests that reuse the same warm environment skip all of that and go straight to the handler, which is why cold starts are occasional rather than constant under steady traffic.

Cold start duration is influenced by package size, runtime choice (compiled languages like Java/.NET are typically slower to initialize than Node.js/Python), memory allocation, and whether the function is attached to a VPC.

Take quiz
A cold start happens when:
Every single invocation of any function
Lambda must create a new execution environment before running the handler
The function's memory is set below 128 MB
A function is invoked from Lambda@Edge only
Which factor typically increases cold-start duration?
A smaller deployment package
Using provisioned concurrency
A larger deployment package with heavy dependencies
Running with 10,240 MB of memory instead of 128 MB

11. What is the maximum execution timeout for a Lambda function?

A Lambda function can run for a maximum of 15 minutes (900 seconds) per invocation; the default timeout when you first create a function is only 3 seconds, which is far too short for most real workloads and is usually the first setting people raise.

If your code hasn't returned by the configured timeout, Lambda forcibly terminates the execution environment and reports a Task timed out error in CloudWatch Logs, and any async invocation retry logic kicks in as if the function had failed.

Timeout is set per function (or per version) alongside memory, and it should be set with headroom above the function's typical (p99) duration rather than tuned to the exact average, since downstream dependencies (databases, APIs) can spike unpredictably.

Workloads genuinely needing longer than 15 minutes should be redesigned as a Step Functions state machine or moved to a different compute service such as AWS Batch or ECS.

Take quiz
The absolute maximum timeout Lambda allows for one invocation is:
3 seconds
5 minutes
15 minutes
1 hour
The default timeout for a newly created Lambda function is:
3 seconds
30 seconds
1 minute
15 minutes

12. Describe the event source mapping in Lambda?

An event source mapping is a Lambda resource that continuously polls a stream or queue on your behalf - for sources like Amazon SQS, Kinesis Data Streams, DynamoDB Streams, and Amazon MQ - and invokes your function synchronously with a batch of records once enough arrive or a batching window elapses.

This differs from push-based triggers (like S3 or API Gateway), where the source itself calls Lambda directly; here, the Lambda service manages the polling loop, checkpointing, and scaling of pollers internally.

Key tunables include batch size, maximum batching window, and for streams, parallelization factor (multiple batches per shard) and starting position (TRIM_HORIZON/LATEST).

Because polling failures block a given shard or partition until resolved (for streams), configuring retry limits, bisecting batches on error, and destinations for failed records are important parts of designing a resilient mapping.

Take quiz
An event source mapping is Lambda's mechanism for:
Directly rendering a web UI
Polling sources like SQS or Kinesis and invoking the function with batches
Storing function code in S3
Encrypting environment variables
Which setting controls how many records Lambda groups per invocation from a stream?
Timeout
Batch size
Memory allocation
Execution role

13. What are the types of Lambda invocation models?

Lambda supports three invocation models, and understanding which one a given trigger uses is essential for reasoning about retries and error handling.

Model Behavior Example Triggers
Synchronous Caller waits for the response; errors are returned immediately to the caller. API Gateway, ALB, direct SDK Invoke
Asynchronous Event is queued internally; Lambda retries on failure and can route to a DLQ/destination. S3, SNS, EventBridge
Poll-based (event source mapping) Lambda service polls the source and invokes synchronously with a batch. SQS, Kinesis, DynamoDB Streams

Choosing the right mental model matters: a synchronous caller (like API Gateway) needs your function to return quickly and propagate meaningful status codes, while asynchronous and poll-based sources rely on Lambda's own retry and failure-handling configuration instead.

Take quiz
Which invocation model has the caller wait for an immediate response?
Synchronous
Asynchronous
Poll-based
Scheduled
S3 event notifications invoke Lambda using which model?
Poll-based event source mapping
Synchronous, blocking S3 until Lambda finishes
Asynchronous invocation
Lambda@Edge only

14. List the triggers that can invoke a Lambda function?

Lambda can be triggered by dozens of AWS services and direct calls; the most commonly used ones fall into a few categories.

  • API/web: Amazon API Gateway, Application Load Balancer, Lambda function URLs.
  • Storage/data events: Amazon S3 (object created/removed), DynamoDB Streams.
  • Messaging: Amazon SQS, Amazon SNS, Amazon MQ.
  • Streaming: Amazon Kinesis Data Streams, Amazon MSK (Kafka).
  • Scheduling/events: Amazon EventBridge (rules, schedules), CloudWatch Alarms.
  • Content delivery: Amazon CloudFront via Lambda@Edge.
  • Auth/identity: Amazon Cognito triggers (pre sign-up, post confirmation, etc.).
  • Orchestration/direct: AWS Step Functions, and direct Invoke calls via SDK or CLI.

Each trigger shapes the event object differently, so handler code typically starts by parsing the specific structure that source sends (for example, Records[].s3.object.key for S3, versus Records[].Sns.Message for SNS).

Take quiz
Which service commonly triggers Lambda for real-time database change events?
DynamoDB Streams
Amazon Route 53
AWS Budgets
Amazon WorkSpaces
Which Lambda trigger type lets code run at CloudFront edge locations?
Lambda@Edge via CloudFront
EventBridge Scheduler
Cognito pre-token-generation
AWS Config rules

15. What is the purpose of the AWS Lambda context object?

The context object, passed as the second argument to the handler, exposes runtime and invocation metadata that isn't part of the business event itself.

Property/Method What it gives you
getRemainingTimeInMillis() Milliseconds left before the configured timeout fires.
functionName / functionVersion Which function and version is currently executing.
memoryLimitInMB The configured memory size for this invocation.
awsRequestId Unique ID for correlating this invocation across logs.
logGroupName / logStreamName Where this invocation's logs are written in CloudWatch.

A common real-world use is calling getRemainingTimeInMillis() before a slow downstream call so the function can fail gracefully or return partial results instead of hitting a hard timeout.

Take quiz
Which context method tells you how much execution time is left before timeout?
memoryLimitInMB
getRemainingTimeInMillis()
functionVersion
logStreamName
The context object is passed to the handler as:
The first argument, replacing the event
The second argument, alongside the event
A global variable only, never an argument
Part of the response body

16. How do you set memory allocation for a Lambda function?

Memory is set in the function's configuration - via console, CLI (aws lambda update-function-configuration --memory-size), or IaC templates - as a value between 128 MB and 10,240 MB, adjustable in 1 MB increments.

What makes this setting distinctive is that Lambda allocates CPU power proportionally to memory: a function configured with more memory also gets a larger share of vCPU, which is why CPU-bound functions often finish faster (and sometimes cheaper overall) at a higher memory setting despite the higher per-millisecond price.

At around 1,769 MB a function effectively gets the equivalent of one full vCPU, and functions can be granted multiple vCPUs at higher memory tiers.

Because the right value depends on the workload, teams often use tools like AWS Lambda Power Tuning to benchmark cost versus duration across memory settings rather than guessing.

Take quiz
Increasing a Lambda function's memory setting also increases:
Only the storage in /tmp
Its proportional share of CPU power
The maximum timeout allowed
The number of layers it can use
The valid memory range for a Lambda function is:
64 MB to 1024 MB
128 MB to 10,240 MB
256 MB to 3,008 MB only
1 GB to 100 GB

17. What is Lambda@Edge?

Lambda@Edge lets you run Lambda functions at Amazon CloudFront edge locations around the world, close to end users, rather than in a single AWS region.

You can hook into four points in a CloudFront request lifecycle: viewer request, origin request, origin response, and viewer response - for example, rewriting a viewer request's URL, or adding security headers to an origin response before it's cached.

It has tighter constraints than regional Lambda: only the Node.js and Python runtimes are supported, functions must be authored in the us-east-1 region before CloudFront replicates them, environment variables and layers aren't supported, and execution time/memory limits are smaller for viewer-triggered events than for origin-triggered ones.

Typical uses include A/B testing at the edge, header-based redirects, image resizing hints, and lightweight authentication/authorization checks before a request reaches the origin.

Take quiz
Lambda@Edge functions must originally be created in which region?
eu-west-1
us-east-1
ap-south-1
Whichever region the origin is in
Which of these is NOT a valid Lambda@Edge trigger point?
Viewer request
Origin response
Database write
Origin request

18. What is the purpose of a dead-letter queue in Lambda?

A dead-letter queue (DLQ) is an optional SQS queue or SNS topic that captures the event payload from an asynchronous invocation after Lambda has exhausted its automatic retries and still failed to process it.

Without a DLQ configured, an event that keeps failing async processing is simply discarded once retries and the maximum event age are exceeded, which means silent data loss unless you're watching CloudWatch metrics closely.

Routing failed events to a DLQ lets you inspect, replay, or alert on them instead of losing them - a common pattern is a CloudWatch alarm on the DLQ's message count.

DLQs are considered the older mechanism; AWS now recommends on-failure destinations (SQS, SNS, another Lambda function, or EventBridge) for async invocations, since destinations also capture invocation metadata like the error and can also record on-success outcomes, not just failures.

Take quiz
A DLQ captures the payload of an asynchronous invocation when:
The function succeeds on the first try
Lambda has exhausted retries and processing still failed
The function times out at exactly 15 minutes only
The event source mapping is disabled
Compared to a DLQ, an on-failure destination additionally offers:
No configuration options at all
Richer invocation metadata and support for success outcomes too
Guaranteed real-time delivery under 1ms
Automatic code deployment on failure

19. Why do we use provisioned concurrency in Lambda?

Provisioned concurrency keeps a specified number of execution environments pre-initialized and warm, so incoming requests skip the cold-start init phase entirely and go straight to handler execution with consistently low latency.

It's used for latency-sensitive workloads - synchronous APIs, user-facing endpoints, or functions with heavy initialization (large SDK clients, ML model loading) - where even an occasional multi-hundred-millisecond cold start would violate an SLA.

Unlike normal on-demand Lambda, provisioned concurrency is billed for the time it's configured, whether or not it's actively invoked, in addition to standard per-invocation duration charges, so it trades cost predictability for latency guarantees.

It's commonly paired with Application Auto Scaling to raise or lower the provisioned amount on a schedule or based on utilization, matching known traffic patterns like a morning spike.

Take quiz
The main benefit of provisioned concurrency is:
Lower per-GB-second pricing
Eliminating cold starts by keeping environments pre-warmed
Unlimited execution timeout
Automatic multi-region replication
Provisioned concurrency billing applies:
Only when the function is actually invoked
For the configured duration, whether invoked or not, plus normal invocation charges
Only during the first 24 hours after configuration
Never - it is a free feature

20. How does Lambda handle concurrency limits?

Every AWS account has a regional concurrent execution limit (a soft limit, commonly starting at 1,000, raisable via support request) shared across all functions in that account and region.

Within that pool, you can set reserved concurrency on a specific function to guarantee it a slice of that pool and, simultaneously, cap how high it can scale - protecting downstream systems like a relational database from being overwhelmed.

Any function without reserved concurrency draws from the shared unreserved pool; if the account limit is reached, further invocation attempts are throttled and return a TooManyRequestsException (HTTP 429) to synchronous callers, or are retried automatically for async/poll-based sources.

Monitoring the ConcurrentExecutions and Throttles CloudWatch metrics is the standard way to catch this before it affects users.

Take quiz
What happens to a synchronous invocation when the account concurrency limit is hit?
It queues indefinitely with no error
It is throttled and returns a 429 TooManyRequestsException
It automatically increases memory to compensate
It is routed to a different AWS account
Reserved concurrency on a function does what?
Guarantees and caps that function's slice of the concurrency pool
Increases the account-wide limit automatically
Disables all retries for that function
Applies only to Lambda@Edge functions

21. What is the difference between concurrency and parallelism in Lambda?

Concurrency in Lambda refers to the number of execution environments actively processing invocations at the same instant - it's the scaling dial the service uses to handle load. Parallelism refers to work genuinely happening at the same time, which within a single environment depends on your code (multi-threading) rather than Lambda's scaling behavior.

Aspect Concurrency Parallelism
Controlled by Lambda's scaling + reserved/provisioned settings Your code's threading/async logic inside one environment
Unit Number of execution environments Number of tasks truly running simultaneously on available vCPUs
Scaling method Horizontal - more environments Vertical - more vCPU/threads within one environment

In practice, Lambda achieves high throughput mainly through concurrency (many parallel environments each handling one invocation), while parallelism inside a single invocation is limited by the vCPUs granted at your configured memory level.

Take quiz
Lambda primarily scales to handle more load by increasing:
Concurrency - spinning up more execution environments
The account's IAM permissions
The function's timeout setting
The number of layers attached
Parallelism within a single Lambda execution environment depends mostly on:
The region the function is deployed in
The code's own threading/async design and available vCPUs
The event source mapping's batch size only
The function's ARN

22. How does Lambda scale to handle multiple requests?

Lambda scales horizontally and automatically: for each concurrent request beyond what existing warm environments can absorb, it spins up a new, isolated execution environment running your code, up to the account/function's concurrency limits.

Scaling isn't unlimited-instantly - accounts get an initial burst capacity (historically 500-3,000 concurrent executions depending on region) available immediately, after which concurrency increases at a steady rate (roughly 500 additional executions per minute) until it hits the account's overall limit.

For poll-based sources like Kinesis or DynamoDB Streams, scaling is additionally bound by the number of shards, since Lambda processes each shard with one poller at a time (unless parallelization factor is increased).

This model means a sudden traffic spike can briefly cause throttling on very bursty workloads even before the account-level cap is reached, which is why reserved/provisioned concurrency and client-side backoff matter for spiky traffic.

Take quiz
Lambda scales to more traffic mainly by:
Increasing memory of a single environment indefinitely
Creating additional isolated execution environments in parallel
Merging requests into fewer environments
Switching runtimes automatically
For a Kinesis-triggered function, concurrency is fundamentally bound by:
The number of shards in the stream
The function's memory setting
The number of layers attached
The AWS account's billing plan

23. When should you use synchronous vs asynchronous invocation?

Use synchronous invocation when the caller needs the function's result immediately to continue its own logic - the classic case is API Gateway or an ALB calling Lambda to build an HTTP response, where the client is waiting on the line.

Use asynchronous invocation when the caller just needs to hand off an event and move on - S3 notifying Lambda of a new upload, or SNS fanning out to multiple functions, where nothing is blocked waiting on the function's result.

Aspect Synchronous Asynchronous
Errors Returned directly to the caller Retried by Lambda (default 2 retries), then DLQ/destination
Typical sources API Gateway, ALB, direct Invoke S3, SNS, EventBridge
Caller behavior Blocks until response or timeout Returns immediately after event is accepted

Choosing wrong shows up quickly: forcing a long-running batch job to run synchronously behind an API Gateway request risks hitting API Gateway's own 29-second integration timeout.

Take quiz
A user-facing API endpoint that needs an immediate HTTP response should use:
Asynchronous invocation
Synchronous invocation
Poll-based invocation only
No invocation model applies to APIs
If an asynchronously invoked function fails, Lambda by default:
Immediately deletes the function
Retries it automatically before giving up
Silently ignores the failure with no retry
Converts it to a synchronous call

24. What is the difference between Lambda and EC2 for compute?

Lambda and EC2 sit at different points on the control-versus-convenience spectrum for running code.

Aspect AWS Lambda Amazon EC2
Server management None - fully managed You manage the OS, patching, scaling
Billing Per request + duration (ms-level) Per instance-hour/second while running, even if idle
Scaling Automatic, near-instant, per request Manual or via Auto Scaling groups, slower to react
Max runtime 15 minutes per invocation Unbounded - can run continuously
Best fit Event-driven, bursty, short-lived tasks Long-running processes, custom OS/software needs, steady high load

A practical rule of thumb: choose Lambda when workloads are event-driven and short, and EC2 (or containers on ECS/EKS) when you need long-running processes, specialized OS-level control, or workloads where sustained high utilization makes always-on instance pricing cheaper than per-invocation billing.

Take quiz
Which is true of EC2 but not Lambda?
You are billed while the instance is idle and running
It has no maximum execution duration per invocation
Both A and B
It automatically scales per individual request with zero configuration
Lambda is generally the better fit for:
Always-on, steady, long-running background daemons
Short, event-driven, bursty workloads
Workloads needing a custom Linux kernel
Applications requiring root-level OS access

25. How do you use VPC with a Lambda function?

You attach a Lambda function to a VPC by specifying one or more subnets and at least one security group in its network configuration - this is required whenever the function needs to reach resources that aren't publicly reachable, like an RDS instance or an internal ElastiCache cluster.

Once attached, Lambda creates elastic network interfaces (ENIs) in the specified subnets so the execution environment can route traffic into that VPC's private network.

A common mistake is forgetting that a VPC-attached function still needs a path to the public internet for calls to non-VPC AWS services (like most S3/DynamoDB endpoints) or third-party APIs - that requires routing through a NAT gateway in a private subnet, or using a VPC endpoint for AWS-service-only traffic.

VpcConfig:
  SubnetIds:
    - subnet-0abc123
    - subnet-0def456
  SecurityGroupIds:
    - sg-0123456789

Take quiz
Attaching Lambda to a VPC is required when the function needs to reach:
Public S3 endpoints only
Private resources like an RDS instance inside that VPC
The Lambda console itself
CloudWatch Logs exclusively
A VPC-attached Lambda function needs which component to reach the public internet?
A NAT gateway in a private subnet (or equivalent routing)
A dead-letter queue
A Lambda layer
An IAM execution role alone

26. Why does a Lambda function in a VPC take longer to start?

Historically, attaching Lambda to a VPC added significant cold-start latency because Lambda had to create a dedicated elastic network interface (ENI) for each unique subnet/security-group combination on demand, and ENI creation could take several seconds.

AWS re-architected this with the Hyperplane-based networking model (rolled out around 2019), which pre-creates and shares ENIs across functions and execution environments in the same account/VPC/subnet combination, largely eliminating the old per-invocation ENI delay.

Some residual latency can still appear on the very first cold start for a brand-new subnet/security-group pairing in an account, since the shared ENI pool for that combination has to be established once - after that, subsequent functions reusing the same networking configuration benefit from the existing pool.

In practice, VPC attachment today adds only a small, mostly one-time cost rather than the multi-second penalty seen before the Hyperplane change.

Take quiz
The Hyperplane networking improvement primarily reduced VPC cold-start latency by:
Removing the need for security groups entirely
Pre-creating and sharing ENIs across functions in the same VPC/subnet
Increasing the maximum timeout to 1 hour
Disabling VPC support altogether
Before the Hyperplane model, VPC cold starts were slow mainly due to:
On-demand ENI creation per unique network configuration
Excessive IAM permission checks
Lack of available memory tiers
DNS caching in CloudFront

27. How is Lambda function versioning managed?

Every function starts with a mutable pointer called $LATEST, which always reflects the most recently deployed code and configuration.

Calling Publish Version takes an immutable snapshot of $LATEST at that moment - code, configuration, and layers - and assigns it a sequential number (1, 2, 3…). Once published, a version's code can never be changed; you can only create a new version for further changes.

Each version has its own unique ARN, so downstream systems can pin to an exact, unchanging version if they need reproducibility, while $LATEST keeps evolving as you keep deploying.

Versioning by itself is rarely used directly by callers in production - it's the foundation that aliases build on to support traffic shifting and safer rollouts.

Take quiz
Which pointer always reflects the most recently deployed code?
$LATEST
A published version like "3"
The execution role
An event source mapping
Once a version is published, its code:
Can still be edited in place
Becomes immutable and cannot be changed
Is automatically deleted after 30 days
Is merged back into $LATEST

28. What is the difference between Lambda aliases and versions?

A version is an immutable, numbered snapshot of a function's code and configuration; an alias is a named, mutable pointer that references one (or, with weighting, two) versions.

Aspect Version Alias
Mutability Immutable once published Mutable - can be repointed anytime
Naming Sequential numbers (1, 2, 3…) Custom names like "prod" or "staging"
Traffic shifting Not supported directly Supports weighted splits across two versions
Typical use Historical, reproducible snapshot What clients/triggers actually target

In practice, teams point their API Gateway integration or event trigger at an alias like prod, then shift that alias between versions for canary or blue/green style releases - clients never need to know the underlying version number changed.

Take quiz
Which of these can shift a percentage of traffic between two versions?
An alias with weighted routing
The execution role
A Lambda layer
The $LATEST pointer alone
What is immutable once created?
An alias
A published version
An environment variable at runtime
The account's concurrency limit

29. How do you troubleshoot a Lambda timeout error?

Start with the REPORT line that CloudWatch Logs writes for every invocation - it shows actual Duration versus the configured timeout, plus Billed Duration and Max Memory Used, which quickly tells you whether the function is close to the limit or wildly exceeding it.

  1. Check whether the timeout is a one-off spike or consistent, using CloudWatch's Duration metric over time.
  2. Look for slow downstream calls - a database query, a third-party API, or a cold connection inside a VPC - using AWS X-Ray tracing to see a breakdown of time spent per segment.
  3. Rule out cold-start-inflated duration versus genuine handler slowness by comparing Init Duration against handler execution time in the logs.
  4. Check for retry loops: if a downstream call itself retries internally with long backoff, it can silently eat the whole timeout budget.

Once the bottleneck is identified, the fix is usually one of: raising the timeout (with headroom), increasing memory (more CPU can speed up CPU-bound work), fixing the slow dependency, or redesigning the flow (e.g., moving heavy work to Step Functions or SQS).

Take quiz
The CloudWatch Logs REPORT line is useful for troubleshooting timeouts because it shows:
The function's IAM policy JSON
Actual duration, billed duration, and max memory used
The VPC's route table
The account's monthly bill
Which AWS service gives a detailed trace of time spent across downstream calls in a Lambda invocation?
AWS X-Ray
Amazon Route 53
AWS Config
Amazon Cognito

30. When would you choose Step Functions over chaining Lambdas directly?

Choose Step Functions when a workflow has multiple steps with branching logic, needs built-in retry/error-handling per step, must pause and wait (for a human approval or an external callback), or needs to run longer than Lambda's 15-minute cap by orchestrating multiple invocations over time.

Having one Lambda function directly invoke another to "chain" logic is a known anti-pattern: it hides the workflow's shape in code instead of a visual, auditable state machine, doubles the compute you pay for (the caller function sits billed and idle while waiting on the callee), and risks runaway recursive costs if a bug causes repeated self-invocation.

Step Functions instead models each Lambda call as a discrete state in a state machine, giving you a visual execution history, native retry/catch policies per state, parallel and choice branches, and integration with dozens of AWS services without extra glue code.

Simple, single-purpose functions triggered independently by events (no orchestration needed) don't need Step Functions at all - it earns its complexity only once multi-step coordination is genuinely required.

Take quiz
A key risk of one Lambda function invoking another directly to chain logic is:
Improved cost efficiency
Doubled billed compute time and potential runaway recursive invocations
Automatic visual workflow diagrams
Guaranteed sub-second latency
Step Functions is the better choice when a workflow needs:
A single, unconditional function call with no branching
Multi-step orchestration with retries, branching, and wait states
Nothing but a cron-style schedule
To run only inside Lambda@Edge

31. What is the difference between reserved concurrency and provisioned concurrency?

These two settings sound similar but solve different problems and are often used together.

Aspect Reserved Concurrency Provisioned Concurrency
Purpose Guarantee and cap a function's slice of the account's concurrency pool Keep environments pre-warmed to remove cold starts
Cold starts Not addressed - still occur normally Eliminated for the provisioned amount
Cost impact No extra charge by itself Billed for the reserved time regardless of invocations
Effect on other functions Reduces the shared pool available to others No effect on the account-wide pool

A latency-critical function often sets both: reserved concurrency to guarantee capacity isn't stolen by other functions, and provisioned concurrency (at or below that reserved amount) to guarantee those available environments are already warm.

Take quiz
Which setting directly eliminates cold starts?
Reserved concurrency
Provisioned concurrency
Dead-letter queue configuration
Environment variable encryption
Reserved concurrency mainly affects:
How warm the execution environment is
How much of the account's concurrency pool the function can use, and reserves it from others
The function's runtime language
The maximum deployment package size

32. How does Lambda retry failed asynchronous invocations?

For asynchronous invocations, Lambda automatically retries a failed execution up to two additional times by default (three attempts total), with a short delay between attempts that increases as retries progress.

You can tune this via MaximumRetryAttempts (0, 1, or 2) and MaximumEventAgeInSeconds (from 60 seconds up to 6 hours) - once either limit is hit, the event is either dropped, sent to a configured dead-letter queue, or routed to an on-failure destination if one is set.

Because retries redeliver the same event, handlers invoked asynchronously should be written to be safe against being run more than once for the same input - this is the same idempotency concern that applies to poll-based sources.

Note this retry behavior is specific to asynchronous invocation; synchronous callers and poll-based event source mappings have their own, different retry semantics.

Take quiz
By default, how many retry attempts does Lambda make for a failed async invocation?
Zero
Up to 2 additional attempts
Unlimited retries
Exactly 10
What can you configure to control how long Lambda keeps retrying an async event?
MaximumEventAgeInSeconds
The execution role's ARN
The function's memory size
The deployment package format

33. Why should you keep Lambda functions stateless?

Lambda freely creates, reuses, and destroys execution environments based on traffic - you cannot predict or guarantee which environment (if any) will handle the next invocation, so any in-memory or local state from a previous call may or may not still be there.

Relying on that unpredictable reuse for correctness - like counting requests in a global variable and expecting an accurate total, or assuming a file written to /tmp will exist for the next invocation - leads to bugs that are hard to reproduce, since behavior differs between cold and warm invocations and across concurrent environments.

Designing handlers to be stateless means every invocation reads whatever state it needs from an external, durable store - DynamoDB, S3, ElastiCache, RDS - and writes results back the same way, so correctness doesn't depend on which environment happens to run it.

Global-scope variables and /tmp are still useful, but only as a performance optimization for caching (like a database connection or a downloaded reference file) - never as the sole source of truth.

Take quiz
Why is relying on in-memory state across invocations risky in Lambda?
Because /tmp storage is always deleted instantly
Because you can't guarantee the same execution environment handles the next invocation
Because global variables are illegal in Lambda
Because it violates the 15-minute timeout
Where should durable, authoritative state actually live for a Lambda-based app?
In a global in-memory variable only
In an external durable store like DynamoDB or S3
In the function's environment variables
In the execution role

34. How do you optimize Lambda cold start times?

Cold-start optimization usually combines several smaller improvements rather than one silver bullet.

  1. Trim the deployment package - remove unused dependencies and split large libraries into layers only when actually needed.
  2. Initialize expensive objects outside the handler (SDK clients, DB connections) so they're created once per environment, not per invocation.
  3. Choose a faster-starting runtime where possible - interpreted runtimes like Node.js/Python typically cold-start faster than JVM-based ones.
  4. Use provisioned concurrency for latency-critical paths where cold starts are unacceptable.
  5. Use SnapStart (for supported runtimes like Java) to resume from a pre-initialized snapshot instead of running init from scratch.
  6. Avoid unnecessary VPC attachment, and when required, keep it simple since ENI/network setup adds a small but real overhead.
  7. Raise memory where the function is CPU-bound during init, since more memory also grants more CPU.

Measuring with the Init Duration field in CloudWatch Logs before and after each change is the only reliable way to confirm which optimizations actually move the needle for a specific function.

Take quiz
Which practice reduces cold starts by avoiding repeated setup work?
Creating SDK clients inside the handler on every call
Initializing SDK clients and connections outside the handler, in global scope
Increasing the deployment package size
Disabling CloudWatch Logs
For Java functions, SnapStart specifically helps cold starts by:
Deleting the function's logs
Resuming execution from a pre-initialized snapshot instead of running init from scratch
Increasing the account concurrency limit
Disabling the execution role

35. What happens when a Lambda function exceeds its memory limit?

If a function tries to use more memory than its configured limit, Lambda terminates the execution environment immediately - the invocation fails, typically with a runtime error such as Runtime exited with error: signal: killed Runtime.ExitError, rather than a graceful exception your code can catch.

This is distinct from a timeout: memory exhaustion kills the process outright, and it can happen well before the configured timeout is reached if the workload is memory-hungry (large payload processing, big in-memory data structures, memory leaks across warm invocations).

For asynchronous or poll-based invocations, this failure is treated like any other function error and triggers the normal retry behavior for that invocation model; for synchronous callers, the error is returned immediately.

The Max Memory Used field in the CloudWatch Logs REPORT line, and the Memory Utilization insight (via Lambda Insights), are the standard signals for catching functions that are close to or hitting their memory ceiling before it causes production failures.

Take quiz
Exceeding the configured memory limit causes Lambda to:
Automatically double the memory and continue
Terminate the execution environment and fail the invocation
Silently ignore the overage
Pause execution until memory frees up
Which log field helps you see how close a function is to its memory ceiling?
Max Memory Used in the REPORT line
The function's ARN
The execution role's trust policy
The deployment package's checksum

36. Explain the execution flow of a Lambda function from invocation to response?

When a trigger calls Lambda, the service first checks for an available warm execution environment; if none exists, it provisions a new one (a cold start), which involves downloading the code, starting the runtime, and running any initialization code outside the handler.

sequenceDiagram
    participant Client
    participant LambdaService as Lambda Service
    participant Env as Execution Environment
    Client->>LambdaService: Invoke(event)
    alt No warm environment
        LambdaService->>Env: Create environment (Init phase)
        Env->>Env: Download code, start runtime, run init code
    end
    LambdaService->>Env: Invoke phase - call handler(event, context)
    Env->>Env: Execute handler logic
    Env-->>LambdaService: Return result or error
    LambdaService-->>Client: Response (sync) / ack (async)
    Note over Env: Environment frozen, kept warm for reuse

Once the handler returns, Lambda sends the result back (immediately, for synchronous callers) and then freezes the environment rather than destroying it, hoping to reuse it for a subsequent invocation and skip the init phase next time.

If no new invocation arrives within an internal idle window, or a new code/version deployment supersedes it, the environment is eventually torn down, and the next request starts the cycle over as a fresh cold start.

Take quiz
After a handler finishes, Lambda typically:
Immediately destroys the execution environment every time
Freezes the environment, hoping to reuse it for future invocations
Restarts the entire AWS account
Deletes the function's code
A cold start's Init phase includes:
Only running the handler's return statement
Downloading code, starting the runtime, and running init code outside the handler
Sending the final HTTP response to the client
Billing calculation only

37. Explain the internal working of the Lambda execution environment lifecycle?

Every execution environment passes through three defined phases, and understanding them is key to reasoning about performance and extension behavior.

Phase What happens
Init Extensions initialize, the language runtime starts, and your code's static/global-scope initialization runs (imports, SDK client creation).
Invoke The handler runs once per event; on a warm environment, this phase repeats directly without re-running Init.
Shutdown Triggered when Lambda decides to reclaim the environment (inactivity, deployment update); extensions receive a SHUTDOWN event to clean up.

Only the Invoke phase repeats across warm invocations - Init runs exactly once per environment's lifetime, which is precisely why moving expensive setup (DB connections, config loading) into global scope, outside the handler, pays off across many subsequent calls.

The environment itself is backed by a lightweight Firecracker microVM, giving strong isolation, and Lambda decides internally when to reuse versus recycle an environment based on traffic patterns, deployments, and internal maintenance - none of which your code can directly control or rely on.

Take quiz
Which lifecycle phase repeats on every warm invocation, without re-running init code?
Init
Invoke
Shutdown
None - all phases repeat equally
The Shutdown phase notifies:
Only the billing system
Extensions, via a SHUTDOWN event, to clean up
The IAM execution role to revoke itself
CloudFront edge caches

38. How can you optimize Lambda function performance for high-throughput workloads?

High-throughput performance tuning spans configuration, code structure, and architecture choices working together.

  1. Right-size memory/CPU using AWS Lambda Power Tuning to find the cost/performance sweet spot rather than guessing.
  2. Reuse connections and clients (HTTP keep-alive, database connection pools) in global scope so warm invocations skip reconnect overhead.
  3. Batch where the trigger allows it - larger SQS/Kinesis batch sizes amortize per-invocation overhead across more records.
  4. Use provisioned concurrency to avoid throughput dips from cold starts during traffic ramps.
  5. Prefer Graviton (ARM) architecture where dependencies support it, for better price-performance.
  6. Avoid unnecessary synchronous chains - fan work out asynchronously (SQS, EventBridge) instead of one function blocking on another.
  7. Keep the deployment package lean so even the occasional cold start is fast.

Because these levers interact - bigger batches reduce invocation count but can raise per-invocation duration and risk timeouts - changes should be load-tested with realistic traffic rather than optimized in isolation.

Take quiz
Which architecture often gives better price-performance for supported Lambda workloads?
x86_64 exclusively
Graviton (ARM64)
SPARC
PowerPC
Increasing SQS batch size for a Lambda trigger mainly helps by:
Reducing invocation overhead by processing more records per call
Eliminating the need for an execution role
Guaranteeing zero cold starts
Disabling retries automatically

39. What is the difference between Lambda SnapStart and provisioned concurrency?

Both features target cold-start latency, but they solve it in fundamentally different ways.

Aspect SnapStart Provisioned Concurrency
Mechanism Caches a Firecracker microVM snapshot after one-time init, taken at publish, and resumes from it on cold start Keeps a set number of full environments running and warm continuously
Runtime support Originally Java; expanded to other managed runtimes over time (check current docs for coverage) All runtimes
Cost model Small per-restore charge, no charge for idle warm capacity Billed continuously for the reserved warm capacity, whether invoked or not
Best fit Functions with heavy, deterministic init (JVM class loading) where snapshotting removes most of that cost Any latency-critical function needing guaranteed warm capacity at a known rate

A subtlety with SnapStart: since the runtime resumes from a frozen snapshot, anything unique per environment that shouldn't be reused (like a cached random value or a rotated credential fetched during init) needs to be re-generated after resume, typically via the runtime hooks SnapStart provides for that purpose.

Take quiz
SnapStart reduces cold starts by:
Resuming from a cached, pre-initialized microVM snapshot
Deleting unused layers automatically
Increasing the account concurrency limit
Forcing synchronous invocation only
A known caveat with SnapStart is that:
It works identically for all randomness/unique state without any changes needed
State captured in the snapshot may need explicit re-initialization after resume
It removes the need for an execution role
It disables CloudWatch Logs

40. How does Lambda achieve isolation between concurrent executions?

Each concurrent invocation runs inside its own dedicated execution environment, which is backed by a lightweight, purpose-built virtual machine technology called Firecracker, developed by AWS specifically for secure, fast-booting, minimal-overhead sandboxing.

Firecracker microVMs give each environment its own isolated kernel, memory space, and virtualized devices - this is stronger isolation than a typical container alone provides, while still being lightweight enough to boot in milliseconds.

Within a single environment, Lambda guarantees that only one invocation runs at a time by default (the handler isn't re-entered concurrently), which is why scaling to more concurrent requests means creating more environments rather than sharing one across simultaneous invocations - the exception is response streaming and certain extension behaviors, which have their own concurrency nuances.

Each environment also gets its own ephemeral /tmp storage and network namespace, so state or a crash in one invocation's environment cannot leak into or affect another's.

Take quiz
The virtualization technology underlying Lambda's execution environment isolation is:
Docker Swarm
Firecracker microVMs
Traditional full hardware VMs only
Kubernetes pods
By default, a single Lambda execution environment handles:
Multiple concurrent invocations simultaneously
One invocation at a time before being freed for reuse
Zero invocations, ever
Only invocations from API Gateway

41. Explain the lifecycle of a Lambda execution context?

The execution context is the underlying environment (memory, /tmp, global variables, network connections) that persists across the Init phase and any number of subsequent Invoke phases, until Lambda decides to reclaim it.

stateDiagram-v2
    [*] --> Created: New invocation, no warm env available
    Created --> Initialized: Init phase (runtime + global code runs)
    Initialized --> Invoking: Invoke phase (handler runs)
    Invoking --> Frozen: Handler returns, env kept warm
    Frozen --> Invoking: New invocation reuses this env
    Frozen --> ShuttingDown: Idle timeout or new deployment
    ShuttingDown --> [*]

Between invocations the environment is frozen, not destroyed - CPU is paused but state in memory and /tmp (up to 10 GB) survives, which is why global-scope caching (a DB connection, a downloaded config file) speeds up subsequent warm invocations.

Reclamation isn't predictable or guaranteed at any fixed time: AWS reclaims idle environments opportunistically, and publishing a new version or updating configuration always forces fresh environments rather than reusing old ones, since the old ones no longer match the current code.

Take quiz
Between invocations, a warm execution environment is:
Immediately destroyed and rebuilt
Frozen, retaining memory and /tmp state for potential reuse
Converted into an EC2 instance
Shared simultaneously across two functions
What always forces a fresh execution environment rather than reusing an old one?
A new invocation using the exact same version
Publishing a new version or updating configuration
Reading an environment variable
Calling getRemainingTimeInMillis()

42. How do you implement idempotency in Lambda functions?

Because Lambda's underlying triggers (SQS, Kinesis, async retries) generally guarantee at-least-once delivery, the same event can legitimately reach your handler more than once - idempotency means designing the handler so processing it twice produces the same end result as processing it once.

  1. Extract or generate an idempotency key from the event - a message ID, an order ID, or a hash of the payload.
  2. Record processed keys in a durable store (commonly DynamoDB) using a conditional write (ConditionExpression: attribute_not_exists(id)), so a duplicate key fails the write instead of reprocessing.
  3. Store the original response alongside the key so a genuine retry can return the same cached result instead of redoing side effects.
  4. Set a TTL on the idempotency record so the table doesn't grow unbounded.

Rather than hand-rolling this, the AWS Lambda Powertools library (available for Python, Java, TypeScript, .NET) ships a ready-made idempotency utility that wraps a handler with exactly this DynamoDB-backed pattern, including handling in-flight duplicate requests safely.

Take quiz
Why do Lambda handlers often need to be idempotent?
Because Lambda guarantees exactly-once delivery for every trigger
Because many triggers deliver at-least-once, so the same event can arrive twice
Because idempotency is required by IAM policy syntax
Because it reduces the maximum memory setting
A common way to enforce idempotency is:
Ignoring all incoming event IDs
A conditional write on an idempotency key in a durable store like DynamoDB
Increasing the function's timeout to 15 minutes
Disabling CloudWatch Logs

43. Why doesn't increasing memory always reduce Lambda cost?

Lambda cost is calculated as allocated memory × billed duration (in GB-seconds) times the per-GB-second price, plus a small per-request fee - so raising memory raises the price rate for every millisecond billed.

For CPU-bound code, more memory also means more vCPU, so duration often drops enough to offset (or even beat) the higher rate - net cost can go down even though the price-per-ms went up.

For I/O-bound code - waiting on a network call, a database query, or an external API - extra CPU doesn't make the remote system respond any faster, so duration stays roughly flat while the price-per-ms still increases, making the invocation strictly more expensive with no performance benefit.

This is why blindly raising memory "to make things faster" can backfire on network-heavy functions; the reliable approach is benchmarking actual duration at multiple memory settings (with a tool like AWS Lambda Power Tuning) rather than assuming higher memory always helps.

Take quiz
For an I/O-bound function waiting mostly on network calls, increasing memory typically:
Speeds up the network response time proportionally
Raises cost without meaningfully reducing duration
Automatically decreases the timeout
Has no effect on billing at all
Lambda cost is fundamentally driven by:
Memory allocated multiplied by billed duration, plus a per-request fee
Only the number of layers attached
The function's programming language alone
The number of environment variables set

44. How does Lambda integrate with API Gateway for RESTful APIs?

The most common pattern is Lambda proxy integration, where API Gateway forwards the entire incoming HTTP request - method, headers, query string, path parameters, and body - as a single structured event object to the function, with no transformation in between.

The function is then responsible for returning a specifically shaped response object containing statusCode, headers, and a body string, which API Gateway passes straight back to the client.

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": '{"message": "ok"}'
    }

API Gateway offers two API types for this: REST APIs, which are more feature-rich (usage plans, request validation, mapping templates for non-proxy integration) and HTTP APIs, which are simpler, lower-latency, and cheaper for straightforward Lambda-backed use cases.

A non-proxy (custom) integration is also possible, where API Gateway uses velocity mapping templates to transform the request before it reaches Lambda and the response afterward, but that adds configuration complexity that most teams avoid unless they need strict decoupling from Lambda's event shape.

Take quiz
In Lambda proxy integration, the function must return a response containing:
Only a raw string with no structure
statusCode, headers, and body
An IAM policy document
A CloudFormation template
Compared to REST APIs, HTTP APIs in API Gateway are generally:
Slower and more expensive
Simpler, lower-latency, and cheaper for basic use cases
Incompatible with Lambda entirely
Only usable with Lambda@Edge

45. What is the difference between Lambda's event-driven model and a traditional server model?

A traditional server (a process on EC2, or a container that's always running) sits idle listening for requests continuously, holding memory and CPU reservation whether or not traffic is arriving, and you scale it by adding or resizing instances ahead of demand.

Aspect Lambda (event-driven) Traditional server
Lifecycle Ephemeral - created per burst of events, frozen/reclaimed after Long-running, persistent process
Scaling trigger Each incoming event, scaled automatically by the platform Pre-provisioned capacity or reactive auto-scaling rules
Billing Per request + execution time actually used Per instance-hour regardless of utilization
State Must be externalized - no guaranteed in-memory persistence Can hold in-memory state naturally across requests

The practical trade-off: event-driven Lambda removes idle-capacity waste and operational overhead for bursty or unpredictable workloads, while a traditional server model is often simpler to reason about (and can be cheaper) for steady, high, continuous load where near-constant utilization is expected.

Take quiz
A defining trait of Lambda's event-driven model is that:
Compute exists continuously whether or not events arrive
Execution environments are ephemeral, created and reclaimed around events
Billing is a flat monthly instance fee
State always persists reliably in memory forever
A traditional always-on server is often more cost-effective when:
Traffic is bursty and unpredictable
Utilization is steady and consistently high
There is no traffic at all, ever
Requests never exceed 1 per day

46. How do you secure secrets used by a Lambda function?

The recommended approach is storing secrets in AWS Secrets Manager or Systems Manager Parameter Store (SecureString parameters), rather than hardcoding them or relying solely on plain environment variables, because both services support fine-grained IAM access control, encryption via KMS, and audit logging through CloudTrail.

Secrets Manager additionally supports automatic rotation for supported data stores (RDS, Redshift, DocumentDB) and custom rotation Lambda functions for others, so credentials can change without a manual redeploy.

import boto3, json

_secrets_client = boto3.client("secretsmanager")
_cached_secret = None

def get_db_password():
    global _cached_secret
    if _cached_secret is None:
        resp = _secrets_client.get_secret_value(SecretId="prod/db/password")
        _cached_secret = json.loads(resp["SecretString"])["password"]
    return _cached_secret

Caching the fetched secret in global scope (as above) avoids calling Secrets Manager on every warm invocation, which both reduces latency and avoids unnecessary API cost - combined with the function's execution role scoped to only that specific secret ARN, following least privilege.

Take quiz
Why is caching a fetched secret in global scope beneficial?
It permanently disables encryption
It avoids re-fetching the secret on every warm invocation, reducing latency and API calls
It bypasses the need for an execution role
It automatically rotates the secret
Compared to plain environment variables, Secrets Manager additionally offers:
Automatic rotation support for certain data stores
Unlimited free storage with no IAM controls
A guarantee of zero cold starts
Built-in Lambda@Edge replication

47. Explain how Lambda handles partial batch failures with SQS?

By default, if a Lambda function processing an SQS-triggered batch throws an error, the entire batch is considered failed and every message in it becomes visible again for reprocessing - even the ones that were actually handled successfully - risking duplicate side effects for those.

The fix is enabling ReportBatchItemFailures on the event source mapping's FunctionResponseTypes, which changes the contract: the handler must return an object listing only the message IDs that actually failed, and SQS will delete the successful ones and retry only the failed ones.

def lambda_handler(event, context):
    failures = []
    for record in event["Records"]:
        try:
            process(record["body"])
        except Exception:
            failures.append({"itemIdentifier": record["messageId"]})
    return {"batchItemFailures": failures}

Without this feature enabled, teams often work around the problem by catching exceptions per-record and never letting the handler itself throw, but that pattern silently loses the ability to distinguish and re-queue only the truly failed messages, so ReportBatchItemFailures is the more correct and AWS-recommended fix.

Take quiz
Without ReportBatchItemFailures enabled, one failed record in an SQS batch causes:
Only that record to be retried
The entire batch to be retried, including already-successful records
The queue to be deleted
No retry at all
With ReportBatchItemFailures enabled, the handler must return:
Nothing - the field is ignored
A batchItemFailures list containing only the failed message IDs
The full event unchanged
An HTTP status code

48. How can you monitor and debug Lambda functions in production?

Production observability for Lambda typically layers three tools together.

Tool What it gives you
CloudWatch Logs Per-invocation logs plus the REPORT line (duration, billed duration, max memory used)
CloudWatch Metrics Aggregate signals: Invocations, Errors, Throttles, Duration, ConcurrentExecutions
AWS X-Ray Distributed trace showing time spent in the function versus downstream calls (DB, APIs)

For deeper OS-level visibility (memory pressure, network usage per invocation) beyond what the REPORT line shows, Lambda Insights adds an extension that publishes enhanced metrics automatically.

Good practice on top of the built-in tooling includes structured JSON logging (so logs are queryable in CloudWatch Logs Insights), correlation IDs propagated across services for tracing a single request end-to-end, and CloudWatch Alarms on error rate, throttle count, and DLQ depth so problems surface before customers report them.

Take quiz
Which tool gives a distributed trace of time spent across a Lambda function and its downstream calls?
AWS X-Ray
Amazon Route 53
AWS Config
Amazon Cognito
Structured JSON logging in Lambda mainly helps by:
Making logs queryable and filterable in CloudWatch Logs Insights
Reducing the function's memory allocation automatically
Disabling retries
Replacing the need for an execution role

49. What is the difference between Lambda extensions and Lambda layers?

A layer is a static packaging mechanism - a .zip of libraries or files extracted to /opt at Init time, purely to share dependencies or code across functions without bundling them into every deployment package.

An extension is an active, running process that lives alongside the runtime inside the execution environment and communicates with Lambda through the dedicated Extensions API, receiving lifecycle events (INIT, INVOKE, SHUTDOWN) so it can hook into the invocation lifecycle - for example, flushing telemetry right before shutdown, or enforcing a security check before the handler runs.

Aspect Layer Extension
Nature Static files/code A running process with lifecycle hooks
Typical use Shared libraries, custom runtimes Monitoring/observability agents, security tooling
Types N/A Internal (in-process, same language) or external (separate process, any language)

In practice, many monitoring vendors (Datadog, New Relic, Lumigo) ship their integration as an extension packaged inside a layer - the layer is the delivery mechanism, and the extension is the active behavior it enables.

Take quiz
What fundamentally distinguishes an extension from a layer?
An extension is a static zip file only, like a layer
An extension is an active process using lifecycle hooks via the Extensions API, while a layer is static content
Layers can only contain Python code
Extensions cannot be delivered inside a layer
A monitoring agent that needs to run during INIT and SHUTDOWN phases is best implemented as:
A plain environment variable
A Lambda extension
A dead-letter queue
An IAM execution role

50. How does Lambda pricing work with the free tier and billing model?

Lambda pricing has two core components: a charge per million requests, and a charge per GB-second of compute (memory allocated × execution duration, rounded to the nearest 1ms), with optional additional charges for provisioned concurrency and data transfer.

Component How it's billed
Requests Per invocation, counted per million requests
Duration GB-seconds = memory (GB) × billed duration (seconds)
Provisioned concurrency (optional) Billed per GB-hour for the reserved warm capacity, continuously

The Lambda free tier - unlike many AWS free tiers that expire after 12 months - is perpetual: it includes 1 million free requests and 400,000 GB-seconds of compute per month, every month, for as long as the account exists (check current AWS pricing pages for exact figures, since AWS periodically updates them).

Because cost scales directly with memory × duration, the two biggest levers for cost efficiency are right-sizing memory (avoiding both under- and over-provisioning) and reducing actual execution time - which is why tools like AWS Lambda Power Tuning and profiling with X-Ray are so central to cost optimization, not just performance tuning.

Take quiz
Lambda's free tier, compared to many other AWS free tiers, is notable because it is:
Available for only the first 12 months
Perpetual - available every month for the life of the account
Limited to Lambda@Edge only
Only available with provisioned concurrency
GB-seconds, the core unit of Lambda duration billing, is calculated as:
Memory (GB) multiplied by billed duration (seconds)
Number of requests divided by memory
A fixed flat rate per function regardless of usage
Timeout setting multiplied by number of layers
«
»

Comments & Discussions