DEV Community

S Uma Shankar Reddy
S Uma Shankar Reddy

Posted on

Day 4: AWS Lambda Foundations

To understand event driven architectures like AWS Lambda, you need to understand the events themselves. This section dives in to how events initiate functions to invoke the code within.

Invocation models for running Lambda functions

Event sources can invoke a Lambda function in three general patterns. These patterns are called invocation models. Each invocation model is unique and addresses a different application and developer needs. The invocation model you use for your Lambda function often depends on the event source you are using. It's important to understand how each invocation model initializes functions and handles errors and retries.

To learn more about the different invocation models, select each tab.

Synchronous invocation

When you invoke a function synchronously, Lambda runs the function and waits for a response. When the function completes, Lambda returns the response from the function's code with additional data, such as the version of the function that was invoked. Synchronous events expect an immediate response from the function invocation.

With this model, there are no built-in retries. You must manage your retry strategy within your application code. Lambda sends the events directly to the function and sends the function response directly back to the invoker.

The following AWS services invoke Lambda synchronously:

Amazon API Gateway
Amazon Cognito
AWS CloudFormation
Amazon Alexa
Amazon Lex
Amazon CloudFront

invoking Lambda synchronously: follow developer guide here https://docs.aws.amazon.com/lambda/latest/dg/invocation-sync.html

Asynchronous invocation:
When you invoke a function asynchronously, events are queued and the requestor doesn't wait for the function to complete. This model is appropriate when the client doesn't need an immediate response.

With the asynchronous model, you can make use of destinations. Use destinations to send records of asynchronous invocations to other services. (Select the Destinations tab for more information.)


The following AWS services invoke Lambda asynchronously:

Amazon SNS
Amazon S3
Amazon EventBridge
invoking Lambda asynchronously,follow AWS Lambda Developer Guide
https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html

A destination can send records of asynchronous invocations to other services. You can configure separate destinations for events that fail processing and for events that process successfully. You can configure destinations on a function, a version, or an alias, similarly to how you can configure error handling settings. With destinations, you can address errors and successes without needing to write more code.
configure destination for asynchronous invocation:
https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations
The following diagram shows a function that is processing asynchronous invocations. When the function returns a success response or exits without producing an error, Lambda sends a record of the invocation to an EventBridge event bus. When an event fails all processing attempts, Lambda sends an invocation record to an Amazon Simple Queue Service (Amazon SQS) queue.

Polling invocation:
This invocation model is designed to integrate with AWS streaming and queuing based services with no code or server management. Lambda will poll (or watch) these services, retrieve any matching events, and invoke your functions. This invocation model supports the following services:
Amazon Kinesis
Amazon SQS
Amazon DynamoDB Streams
With this type of integration, AWS will manage the poller on your behalf and perform synchronous invocations of your function.
The configuration of services as event triggers is known as event source mapping. This process occurs when you configure event sources to launch your Lambda functions and then grant theses sources IAM permissions to access the Lambda function.
Lambda reads events from the following services:
Amazon DynamoDB
Amazon Kinesis
Amazon MQ
Amazon Managed Streaming for Apache Kafka (MSK)
self-managed Apache Kafka
Amazon SQS
https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html

Understanding AWS Lambda Permissions: Execution Roles vs. Resource-Based Policies
When building serverless applications, securing your AWS Lambda functions requires a two-sided approach. Because Lambda is deeply integrated with AWS Identity and Access Management (IAM), you have to explicitly define both who can invoke the function (inbound) and what the function can do once it is running (outbound).

To configure this properly, you will use two distinct types of IAM policies.

  1. The Execution Role (Outbound Permissions) The execution role dictates what your Lambda function is allowed to do within your AWS environment. Lambda assumes this role whenever the function is invoked.

Actionable Permissions: The IAM policy attached to this role defines exactly which AWS services the function can interact with (for example, writing to a DynamoDB table or reading from an S3 bucket).

The Trust Policy: The role must include a trust policy granting the Lambda service permission to AssumeRole. This is what allows AWS to act on your behalf.

Least Privilege: Always start with the most restrictive permissions and only add what is strictly necessary. You can use IAM Access Analyzer to review your AWS CloudTrail logs and automatically generate a policy template containing only the permissions your function actually used.

  1. Resource-Based Policies (Inbound Permissions) While the execution role handles what the function does, the resource-based policy (also called a function policy) determines which principals are allowed to trigger it.

Defining the Principal: A principal can be an IAM user, an IAM role, another AWS service (like Amazon S3 or API Gateway), or a completely different AWS account.

Cross-Account Access: Resource policies are the easiest way to grant cross-account access. For example, if a Production S3 bucket needs to invoke a Lambda function in a Dev account, you simply add a resource-based policy to the Dev function allowing that specific S3 service to invoke it.

Size Limits: Resource policies have a size limit. If you need to grant invocation access to dozens of different accounts, you might hit this limit and need to use cross-account IAM roles instead.


Accessing Resources in a VPC
If your function needs to access isolated resources inside a Virtual Private Cloud (VPC), it requires additional configuration (like subnet and security group IDs). Crucially, your execution role will need the AWSLambdaVPCAccessExecutionRole managed policy. This gives Lambda the permissions to create, describe, and delete Elastic Network Interfaces (ENIs).

Additionally, you can use interface VPC endpoints (powered by AWS PrivateLink) to establish a private connection between your VPC and Lambda. This ensures that traffic between your VPC and Lambda APIs never traverses the public internet, completely bypassing the need for an internet gateway or NAT device.

Tip for Easier Management: Managing these policies manually can get tedious as your application grows. Tools like the AWS Serverless Application Model (AWS SAM) simplify this by allowing you to define policies, inline documents, or templates directly alongside your infrastructure code, automatically scoping permissions to the resources used by your application.


title: "Authoring AWS Lambda Functions: Design Patterns, Best Practices, and Deployment"
published: false
description: "Learn the best practices for writing AWS Lambda function code, design patterns, and deployment strategies."

tags: aws, serverless, lambda, programming

AWS Lambda enables developers to run code without provisioning or managing servers. While the serverless model abstracts infrastructure concerns, authoring efficient, maintainable, and scalable Lambda functions requires a solid grasp of Lambda's programming model, architectural best practices, and automated deployment tooling.


1. The AWS Lambda Programming Model

Lambda is designed to let you bring your own code and work with familiar development tools. Rather than rewriting core logic to fit a proprietary paradigm, you make minimal adjustments to adapt your code to Lambda’s event-driven model.

Supported Languages & Environments

Lambda natively supports major runtimes:

  • Node.js
  • Python
  • Java
  • Go
  • C# / .NET
  • Ruby
  • PowerShell
  • Custom Runtimes (via the Lambda Runtime API)

AWS provides plugins and toolkits for popular IDEs, including Visual Studio Code, IntelliJ, Eclipse, and PyCharm.


2. Anatomy of a Lambda Function: The Handler Method

The handler method is the entry point that AWS Lambda executes when your function is invoked. When the handler exits or returns a response, the execution completes, and the container becomes available to process subsequent events.

def lambda_handler(event, context):
    # Process event and execute business logic
    return {
        'statusCode': 200,
        'body': 'Success'
    }
Enter fullscreen mode Exit fullscreen mode

Configuring Your Lambda Functions:
When building and testing serverless applications, function performance and cost efficiency depend heavily on three core configuration settings: Memory, Timeout, and Concurrency.

Configuring these settings requires testing your functions against real-world scenarios and peak traffic. Monitoring and tuning these values ensures both cost optimization and a predictable customer experience.


1. Memory Allocation: The Compute Lever

In AWS Lambda, memory is not just RAM—it is the master dial for all compute resources.

  • Allocation Limits: You can allocate between 128 MB and 10,240 MB (10 GB) to a single function (in 1-MB increments).
  • Proportional Scaling: Lambda allocates CPU power, network bandwidth, and disk I/O linearly in proportion to the amount of configured memory.
  • Multi-threading: At 1,769 MB of memory, a function is allocated the equivalent of one full vCPU. Allocating above this threshold provides multiple vCPUs, enabling multi-threaded execution.
  • Timeout: Setting Guardrails The timeout value defines the maximum duration a function can execute before Lambda forcibly terminates it.

Maximum Timeout: 900 seconds (15 minutes) per single invocation.

Fail Fast Pattern: Setting the timeout to the 15-minute maximum is rarely ideal for production. Set your timeout slightly above the expected P99 duration after load testing. If an upstream dependency hangs, a tight timeout prevents requests from stalling indefinitely and running up compute bills.

1-ms Billing Precision: Lambda bills execution runtime in 1-millisecond increments. Avoiding unnecessarily prolonged runtimes directly reduces overall costs.

  1. Understanding Lambda Billing Mechanics Lambda follows a pay-for-what-you-use pricing model based on two primary dimensions:

Total Requests: Billed per invocation (including console test invocations and event-driven triggers).

Compute Duration (GB-Seconds): Calculated from the moment your code begins executing until it returns or terminates, rounded up to the nearest 1 ms.

⚠️ Key Takeaway: You are billed for the allocated memory, not the memory your code actually consumes. If you allocate 10 GB to a function that only consumes 2 GB, you pay the 10 GB rate for the duration of the execution.

AWS Free Tier
1,000,000 free requests per month.

400,000 GB-seconds of compute time per month.

  1. The Balance Between Memory, Speed, and Cost Counterintuitively, increasing memory can sometimes lower your total AWS bill.

Because CPU scales proportionally with memory, a CPU-bound workload running with 1,024 MB may finish in half the time of the same code running at 512 MB. Even though the hourly compute rate is higher, the drastically reduced duration can result in a lower total cost in GB-seconds.
Deploying and Testing Serverless Application:
Transitioning from traditional server-based application development to serverless architecture requires a shift in how you think about environments, testing, and deployments. In this post, we’ll explore the differences between the two paradigms, and learn how frameworks like the AWS Serverless Application Model (AWS SAM) and deployment tools like AWS CodeDeploy simplify the process of shipping reliable serverless applications.


1. The Deployment Analogy: Moving In vs. Building from Scratch

To understand the difference between traditional and serverless deployments, consider the real-world analogy of buying a house.

Server-Based Deployments: The Prebuilt House

In a server-based model, your deployment environment is like a pre-existing house. Before you move in, you know the layout, the infrastructure, and the constraints (e.g., three bedrooms, two bathrooms). You don’t need to know how the foundation was poured; you just work with what is already there.

When you deploy, you pack your code into boxes and hand it to a DevOps team (the movers). The movers take your boxes to the designated environment (the house) and unpack them onto running server instances. The environment sits idle, waiting for your code.

Serverless Deployments: The Blueprint

A serverless deployment is like designing and building a house from a blueprint. You must specify every detail: the number of rooms, the wiring, the plumbing, and the exact placement of windows.

In AWS, this blueprint is the AWS CloudFormation template (Infrastructure as Code). A CloudFormation template specifies every detail of the Lambda function and the exact environment required to run it. With this blueprint, AWS provisions the exact "house" your application needs every time it deploys, allowing you to replicate identical environments across multiple AWS accounts seamlessly.


2. Shifting the Developer Workflow

The transition to serverless changes the day-to-day workflow for developers, particularly around testing.

Feature Server-Based Workflow Serverless Workflow
Development Pull down local copy of the app. Author code bundled with CloudFormation (blueprint).
Testing Local IDE debugging, deploying to persistent test servers. Cloud-native testing. Local emulation (via SAM CLI) is limited; true testing happens in isolated cloud accounts.
Deployment Hand off code to DevOps to update existing long-running instances. Deploy code + infrastructure as a single immutable package (Stack) to the cloud.

Because serverless relies heavily on cloud-native integrations (e.g., IAM roles, API Gateway, DynamoDB), fully recreating the environment locally is impossible. Instead, developers deploy dedicated stacks to isolated sandbox AWS accounts to perform realistic testing.


3. Simplifying with AWS SAM

Writing raw CloudFormation JSON or YAML can quickly become complex. A simple API endpoint backed by a database might require over 100 lines of boilerplate for IAM roles, API mappings, and table definitions.

AWS SAM (Serverless Application Model) simplifies this. SAM acts as a streamlined shorthand for CloudFormation. It transforms simplified instructions into a fully detailed CloudFormation template during deployment.

Benefits of AWS SAM:

  • Environmental Parity: Ensures you deploy the exact same stack definition to Development, Staging, and Production.
  • Simplified Experimentation: Without the overhead of maintaining server instances, you can easily spin up isolated cloud stacks for different Git feature branches, only paying for the exact invocations you trigger.

4. Mitigating Risk: Versions and Aliases

One challenge with serverless deployments is that updates can go live instantly, potentially overwriting a working production function. To mitigate this risk, AWS Lambda uses Versions and Aliases.

  • $LATEST Version: The default, mutable version of your function. Every time you upload code, it updates $LATEST.
  • Published Versions: An immutable snapshot of your code and configuration (e.g., Version 1, Version 2). Once published, a version cannot be changed.
  • Aliases: A named pointer (e.g., PROD, TEST) that routes traffic to a specific published version. Instead of hardcoding version numbers into your API Gateway or event sources, you point them to an Alias. When you deploy a new version, you simply update the Alias to point to it.

Test Using Alias Routing (Traffic Splitting)

Aliases can point to a maximum of two Lambda function versions simultaneously to facilitate traffic splitting. For example, you can route 90% of traffic to Version 1 and 10% to Version 2 to safely test a new release. Both versions must share the same runtime role and dead-letter queue (DLQ) configuration.


5. Safe Deployments with AWS CodeDeploy

Lambda integrates directly with AWS CodeDeploy to automate rollouts and manage traffic shifting safely. CodeDeploy supports three primary traffic-shifting strategies:

  1. Canary: Traffic is shifted in two increments. (e.g., 10% of traffic is shifted to the new version. If successful after a set time, the remaining 90% is shifted).
  2. Linear: Traffic is shifted in steady, predetermined increments every X minutes (e.g., 10% every 5 minutes).
  3. All-at-Once: Shifts 100% of traffic to the new version immediately.

Rollback Mechanisms

CodeDeploy ensures safety through testing and monitoring options:

  • Hooks: Execute pre-traffic and post-traffic Lambda functions to run automated sanity checks before routing production traffic, and again after the shift completes.
  • Alarms: Integrate with Amazon CloudWatch to monitor error rates during the rollout. If an alarm triggers, CodeDeploy automatically halts the deployment and rolls traffic back to the previous version.

⚠️ Best Practice: When CodeDeploy triggers a rollback, the entire CloudFormation template being deployed rolls back. Keep your SAM/CloudFormation templates scoped as concisely as possible (ideally, one template per microservice) to minimize the blast radius of a rollback.


Summary & Key Takeaways

  • Serverless is Infrastructure as Code: Your deployment artifact is your code plus your environment blueprint (CloudFormation/SAM).
  • Cloud-First Testing: Shift away from local monolith testing toward deploying ephemeral stacks in isolated AWS accounts.
  • Versions & Aliases: Never use $LATEST in production. Publish immutable versions and route traffic using Aliases.
  • Automated Safety: Use AWS CodeDeploy for Canary or Linear traffic shifting, backed by CloudWatch alarms and validation hooks.

Monitoring and Troubleshooting:
AWS Lambda abstracts away underlying infrastructure, but you still need deep visibility into how your code performs in the cloud. Effective monitoring and troubleshooting are critical for maintaining high availability and optimizing the performance of your serverless applications.

This post covers how to use native AWS services—Amazon CloudWatch, Lambda Insights, and AWS X-Ray—to monitor, trace, debug, and troubleshoot your Lambda functions.


1. Built-In Monitoring with Amazon CloudWatch

AWS Lambda automatically monitors functions on your behalf and reports native telemetry to Amazon CloudWatch. Without any extra configuration, Lambda automatically tracks request volume, execution duration, and error rates.

To effectively monitor the health of your serverless applications, you should understand these core built-in metrics:

Metric Description
Invocations The total number of times your function code is executed, including successful runs and errors.
Duration The amount of time your function code spends processing an event (billed in 1-ms increments).
Errors The number of invocations that fail due to errors in your code or timeouts.
Throttles The number of invocation requests rejected because your function reached its concurrency limit.
ConcurrentExecutions The number of function instances processing events simultaneously across your account or specific function.
IteratorAge (For stream sources like Kinesis or DynamoDB) The age of the latest record in the event batch when Lambda receives it. High age indicates processing is falling behind.
DeadLetterErrors The number of times Lambda fails to send a discarded event payload to a configured Dead-Letter Queue (DLQ).

2. Deep System Visibility with CloudWatch Lambda Insights

While standard CloudWatch metrics provide a high-level overview, Amazon CloudWatch Lambda Insights acts as an advanced diagnostic solution. It collects, aggregates, and summarizes system-level metrics (like CPU and memory usage) and diagnostic events (like cold starts and worker shutdowns).

How It Works

Lambda Insights uses a CloudWatch Lambda extension, which is attached to your function as a Lambda Layer. When enabled, the extension collects system-level metrics and emits a single performance log event for every invocation. CloudWatch parses these logs using Embedded Metric Format (EMF) to generate granular dashboards without adding high-latency overhead to your code.

The Lambda Insights Dashboard

The console provides two primary operational views:

  1. Multi-Function Overview: Aggregates runtime metrics for all Lambda functions within the current AWS account and Region. This view is essential for identifying over-utilized or under-utilized functions at a glance.
  2. Single-Function View: Drills down into the specific runtime metrics of an individual function. Use this view to troubleshoot individual request anomalies, memory leaks, or specific cold start spikes.

3. Distributed Tracing with AWS X-Ray

In a microservices architecture, a single user request might traverse an API Gateway, trigger a Lambda function, read from DynamoDB, and push a message to SQS. AWS X-Ray helps you visualize these connected components, identify performance bottlenecks, and trace requests that result in errors across the entire call flow.

X-Ray processes trace data generated by your Lambda functions to create an interactive Service Map and searchable trace summaries.

Use Cases for AWS X-Ray

  • Tuning Performance: Pinpoint exactly which downstream service is slowing down your Lambda function.
  • Call Flow Visualization: Map out the exact path of API calls and AWS service interactions.
  • Bottleneck Identification: View the timing of an invocation broken down into sub-segments.

Analyzing Cold Starts vs. Warm Starts

When analyzing X-Ray traces, you will immediately see the performance difference between a Cold Start and a Warm Start.

  • Cold Start Traces: When an event (e.g., an S3 object creation) triggers a new Lambda environment, the X-Ray trace will show a distinct Initialization (Init) phase. This is the time AWS takes to provision the underlying container, load the runtime, and execute your deployment package initialization code.
  • Warm Start Traces: If a subsequent S3 object is uploaded while the container is still active, the X-Ray trace will show a significantly faster execution. The Initialization phase is entirely absent because the runtime environment and SDK connections are already established and reused.

Summary & Key Takeaways

Tool / Concept Best Used For
CloudWatch Standard Metrics Tracking baseline health: Invocations, Duration, Errors, and Throttles.
CloudWatch Lambda Insights Profiling system-level diagnostics: Memory utilization, CPU usage, and aggregate cold start analysis via Lambda Layers.
AWS X-Ray Distributed tracing: Visualizing end-to-end call flows, mapping downstream dependencies, and measuring exactly where time is spent during a cold or warm start.

Top comments (0)