

# Using Lambda with infrastructure as code (IaC)
Infrastructure as code (IaC)

Lambda functions rarely run in isolation. Instead, they often form part of a serverless application with other resources such as databases, queues, and storage. With [infrastructure as code (IaC)](https://aws.amazon.com/what-is/iac/), you can automate your deployment processes to quickly and repeatably deploy and update whole serverless applications involving many separate AWS resources. This approach speeds up your development cycle, makes configuration management easier, and ensures that your resources are deployed the same way every time.

## IaC tools for Lambda


**CloudFormation**  
CloudFormation is the foundational IaC service from AWS. You can use [YAML or JSON templates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html) to model and provision your entire AWS infrastructure, including Lambda functions. CloudFormation handles the complexities of creating, updating, and deleting your AWS resources.

**AWS Serverless Application Model (AWS SAM)**  
AWS SAM is an open-source framework built on top of CloudFormation. It provides a simplified syntax for defining serverless applications. Use [AWS SAM templates](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html) to quickly provision Lambda functions, APIs, databases, and event sources with just a few lines of YAML.

**AWS Cloud Development Kit (AWS CDK)**  
The CDK is a code-first approach to IaC. You can define your Lambda-based architecture using TypeScript, JavaScript, Python, Java, C\$1/.Net, or Go. Choose your preferred language and use programming elements like parameters, conditionals, loops, composition, and inheritance to define the desired outcome of your infrastructure. The CDK then generates the underlying CloudFormation templates for deployment. For an example of how to use Lambda with CDK, see [Deploying Lambda functions with AWS CDK](lambda-cdk-tutorial.md).

![\[\]](http://docs.aws.amazon.com/lambda/latest/dg/images/IaC_tools.png)


AWS also provides a service called AWS Infrastructure Composer to develop IaC templates using a simple graphical interface. With Infrastructure Composer, you design an application architecture by dragging, grouping, and connecting AWS services in a visual canvas. Infrastructure Composer then creates an AWS SAM template or an CloudFormation template from your design that you can use to deploy your application.

In the [Using Lambda functions in AWS SAM and Infrastructure Composer](foundation-iac-getting-started.md) section below, you use Infrastructure Composer to develop a template for a serverless application based on an existing Lambda function.

# Using Lambda functions in AWS SAM and Infrastructure Composer
Using AWS SAM and Infrastructure Composer

In this tutorial, you can get started using IaC with Lambda by creating an AWS SAM template from an existing Lambda function and then building out a serverless application in Infrastructure Composer by adding other AWS resources.

As you carry out this tutorial, you’ll learn some fundamental concepts, like how AWS resources are specified in AWS SAM. You’ll also learn how to use Infrastructure Composer to build a serverless application you can deploy using AWS SAM or CloudFormation.

To complete this tutorial, you’ll carry out the following steps:
+ Create an example Lambda function
+ Use the Lambda console to view the AWS SAM template for the function
+ Export your function’s configuration to AWS Infrastructure Composer and design a simple serverless application based on your function’s configuration
+ Save an updated AWS SAM template you can use as a basis to deploy your serverless application

## Prerequisites


In this tutorial, you use Infrastructure Composer’s [local sync](https://docs.aws.amazon.com/application-composer/latest/dg/reference-features-local-sync.html) feature to save your template and code files to your local build machine. To use this feature, you need a browser that supports the File System Access API, which allows web applications to read, write, and save files in your local file system . We recommend using either Google Chrome or Microsoft Edge. For more information about the File System Access API, see [What is the File System Access API?](https://docs.aws.amazon.com/application-composer/latest/dg/reference-fsa.html#reference-fsa-api)

## Create a Lambda function


In this first step, you create a Lambda function you can use to complete the rest of the tutorial. To keep things simple, you use the Lambda console to create a basic 'Hello world' function using the Python 3.11 runtime.

**To create a 'Hello world' Lambda function using the console**

1. Open the [Lambda console](https://console.aws.amazon.com/lambda).

1. Choose **Create function**.

1. Leave **Author from scratch** selected, and under **Basic information**, enter **LambdaIaCDemo** for **Function name**.

1. For **Runtime**, select **Python 3.11**.

1. Choose **Create function**.

## View the AWS SAM template for your function


Before you export your function configuration to Infrastructure Composer, use the Lambda console to view your function's current configuration as an AWS SAM template. By following the steps in this section, you'll learn about the anatomy of an AWS SAM template and how to define resources like Lambda functions to start specifying a serverless application.

**To view the AWS SAM template for your function**

1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console.

1. Choose the function you just created (`LambdaIaCDemo`).

1. In the **Function overview** pane, choose **Template**.

   In place of the diagram representing your function’s configuration, you’ll see an AWS SAM template for your function. The template should look like the following.

   ```
   # This AWS SAM template has been generated from your function's 
   # configuration. If your function has one or more triggers, note 
   # that the AWS resources associated with these triggers aren't fully 
   # specified in this template and include placeholder values.Open this template 
   # in AWS Application Composer or your favorite IDE and modify 
   # it to specify a serverless application with other AWS resources. 
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: An AWS Serverless Specification template describing your function.
   Resources:
     LambdaIaCDemo:
       Type: AWS::Serverless::Function
       Properties:
         CodeUri: .
         Description: ''
         MemorySize: 128
         Timeout: 3
         Handler: lambda_function.lambda_handler
         Runtime: python3.11
         Architectures:
           - x86_64
         EventInvokeConfig:
           MaximumEventAgeInSeconds: 21600
           MaximumRetryAttempts: 2
         EphemeralStorage:
           Size: 512
         RuntimeManagementConfig:
           UpdateRuntimeOn: Auto
         SnapStart:
           ApplyOn: None
         PackageType: Zip
         Policies:
           Statement:
             - Effect: Allow
               Action:
                 - logs:CreateLogGroup
               Resource: arn:aws:logs:us-east-1:123456789012:*
             - Effect: Allow
               Action:
                 - logs:CreateLogStream
                 - logs:PutLogEvents
               Resource:
                 - >-
                   arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/LambdaIaCDemo:*
   ```

Let’s take a moment to look at the YAML template for your function and understand some key concepts.

The template starts with the declaration `Transform: AWS::Serverless-2016-10-31`. This declaration is required because behind the scenes, AWS SAM templates are deployed through CloudFormation. Using the `Transform` statement identifies the template as an AWS SAM template file.

Following the `Transform` declaration comes the `Resources` section. This is where the AWS resources you want to deploy with your AWS SAM template are defined. AWS SAM templates can contain a combination of AWS SAM resources and CloudFormation resources. This is because during deployment, AWS SAM templates expand to CloudFormation templates, so any valid CloudFormation syntax can be added to an AWS SAM template.

At the moment, there is just one resource defined in the `Resources` section of the template, your Lambda function `LambdaIaCDemo`. To add a Lambda function to an AWS SAM template, you use the `AWS::Serverless::Function` resource type. The `Properties` of a Lambda function resource define the function’s runtime, function handler, and other configuration options. The path to your function’s source code that AWS SAM should use to deploy the function is also defined here. To learn more about Lambda function resources in AWS SAM, see [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) in the *AWS SAM Developer Guide*.

As well as the function properties and configurations, the template also specifies an AWS Identity and Access Management (IAM) policy for your function. This policy gives your function permission to write logs to Amazon CloudWatch Logs. When you create a function in the Lambda console, Lambda automatically attaches this policy to your function. To learn more about specifying an IAM policy for a function in an AWS SAM template, see the `policies` property on the [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) page of the *AWS SAM Developer Guide*.

To learn more about the structure of AWS SAM templates, see [AWS SAM template anatomy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html).

## Use AWS Infrastructure Composer to design a serverless application


To start building out a simple serverless application using your function’s AWS SAM template as a starting point, you export your function configuration to Infrastructure Composer and activate Infrastructure Composer’s local sync mode. Local sync automatically saves your function’s code and your AWS SAM template to your local build machine and keeps your saved template synced as you add other AWS resources in Infrastructure Composer.

**To export your function to Infrastructure Composer**

1. In the **Function Overview** pane, choose **Export to Application Composer**.

   To export your function's configuration and code to Infrastructure Composer, Lambda creates an Amazon S3 bucket in your account to temporarily store this data.

1. In the dialog box, choose **Confirm and create project** to accept the default name for this bucket and export your function's configuration and code to Infrastructure Composer.

1. (Optional) To choose another name for the Amazon S3 bucket that Lambda creates, enter a new name and choose **Confirm and create project**. Amazon S3 bucket names must be globally unique and follow the [bucket naming rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html).

   Selecting **Confirm and create project** opens the Infrastructure Composer console. On the *canvas*, you’ll see your Lambda function.

1. From the **Menu** dropdown, choose **Activate local sync**.

1. In the dialog box that opens, choose **Select folder** and select a folder on your local build machine.

1. Choose **Activate** to activate local sync.

To export your function to Infrastructure Composer, you need permission to use certain API actions. If you're unable to export your function, see [Required permissions](services-appcomposer.md#services-appcomposer-permissions) and make sure you have the permissions you need.

**Note**  
Standard [Amazon S3 pricing](https://aws.amazon.com/s3/pricing) applies for the bucket Lambda creates when you export a function to Infrastructure Composer. The objects that Lambda puts into the bucket are automatically deleted after 10 days, but Lambda doesn't delete the bucket itself.  
To avoid additional charges being added to your AWS account, follow the instructions in [Deleting a bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html) after you have exported your function to Infrastructure Composer. For more information about the Amazon S3 bucket Lambda creates, see [Using AWS Lambda with AWS Infrastructure Composer](services-appcomposer.md).

**To design your serverless application in Infrastructure Composer**

After activating local sync, changes you make in Infrastructure Composer will be reflected in the AWS SAM template saved on your local build machine. You can now drag and drop additional AWS resources onto the Infrastructure Composer canvas to build out your application. In this example, you add an Amazon SQS simple queue as a trigger for your Lambda function and a DynamoDB table for the function to write data to.

1. Add an Amazon SQS trigger to your Lambda function by doing the following:

   1. In the search field in the **Resources** palette, enter **SQS**.

   1. Drag the **SQS Queue** resource onto your canvas and position it to the left of your Lambda function.

   1. Choose **Details**, and for **Logical ID** enter **LambdaIaCQueue**.

   1. Choose **Save**.

   1. Connect your Amazon SQS and Lambda resources by clicking on the **Subscription** port on the SQS queue card and dragging it to the left hand port on the Lambda function card. The appearance of a line between the two resources indicates a successful connection. Infrastructure Composer also displays a message at the bottom of the canvas indicating that the two resources are successfully connected.

1. Add an Amazon DynamoDB table for your Lambda function to write data to by doing the following:

   1. In the search field in the **Resources** palette, enter **DynamoDB**.

   1. Drag the **DynamoDB Table** resource onto your canvas and position it to the right of your Lambda function.

   1. Choose **Details**, and for **Logical ID** enter **LambdaIaCTable**.

   1. Choose **Save**.

   1. Connect the DynamoDB table to your Lambda function by clicking on the right hand port of the Lambda function card and dragging it to the left hand port on the DynamoDB card. 

Now that you’ve added these extra resources, let’s take a look at the updated AWS SAM template Infrastructure Composer has created.

**To view your updated AWS SAM template**
+ On the Infrastructure Composer canvas, choose **Template** to switch from the canvas view to the template view.

Your AWS SAM template should now contain the following additional resources and properties:
+ An Amazon SQS queue with the identifier `LambdaIaCQueue`

  ```
  LambdaIaCQueue:
      Type: AWS::SQS::Queue
      Properties:
        MessageRetentionPeriod: 345600
  ```

  When you add an Amazon SQS queue using Infrastructure Composer, Infrastructure Composer sets the `MessageRetentionPeriod` property. You can also set the `FifoQueue` property by selecting **Details** on the SQS Queue card and checking or unchecking **Fifo queue**.

  To set other properties for your queue, you can manually edit the template to add them. To learn more about the `AWS::SQS::Queue` resource and its available properties, see [AWS::SQS::Queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html) in the *CloudFormation User Guide*.
+ An `Events` property in your Lambda function definition that specifies the Amazon SQS queue as a trigger for the function

  ```
  Events:
    LambdaIaCQueue:
      Type: SQS
      Properties:
        Queue: !GetAtt LambdaIaCQueue.Arn
        BatchSize: 1
  ```

  The `Events` property consists of an event type and a set of properties that depend on the type. To learn about the different AWS services you can configure to trigger a Lambda function and the properties you can set, see [EventSource](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html) in the *AWS SAM Developer Guide*.
+ A DynamoDB table with the identifier `LambdaIaCTable`

  ```
  LambdaIaCTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        BillingMode: PAY_PER_REQUEST
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        StreamSpecification:
          StreamViewType: NEW_AND_OLD_IMAGES
  ```

  When you add a DynamoDB table using Infrastructure Composer, you can set your table's keys by choosing **Details** on the DynamoDB table card and editing the key values. Infrastructure Composer also sets default values for a number of other properties including `BillingMode` and `StreamViewType`.

  To learn more about these properties and other properties you can add to your AWS SAM template, see [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html) in the *CloudFormation User Guide*.
+ A new IAM policy that gives your function permission to perform CRUD operations on the DynamoDB table you added.

  ```
  Policies:
  ...
    - DynamoDBCrudPolicy:
      TableName: !Ref LambdaIaCTable
  ```

The complete final AWS SAM template should look like the following.

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS Serverless Specification template describing your function.
Resources:
  LambdaIaCDemo:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Description: ''
      MemorySize: 128
      Timeout: 3
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      EventInvokeConfig:
        MaximumEventAgeInSeconds: 21600
        MaximumRetryAttempts: 2
      EphemeralStorage:
        Size: 512
      RuntimeManagementConfig:
        UpdateRuntimeOn: Auto
      SnapStart:
        ApplyOn: None
      PackageType: Zip
      Policies:
        - Statement:
            - Effect: Allow
              Action:
                - logs:CreateLogGroup
              Resource: arn:aws:logs:us-east-1:594035263019:*
            - Effect: Allow
              Action:
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource:
                - arn:aws:logs:us-east-1:594035263019:log-group:/aws/lambda/LambdaIaCDemo:*
        - DynamoDBCrudPolicy:
            TableName: !Ref LambdaIaCTable
      Events:
        LambdaIaCQueue:
          Type: SQS
          Properties:
            Queue: !GetAtt LambdaIaCQueue.Arn
            BatchSize: 1
      Environment:
        Variables:
          LAMBDAIACTABLE_TABLE_NAME: !Ref LambdaIaCTable
          LAMBDAIACTABLE_TABLE_ARN: !GetAtt LambdaIaCTable.Arn
  LambdaIaCQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 345600
  LambdaIaCTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES
```

## Deploy your serverless application using AWS SAM (optional)


If you want to use AWS SAM to deploy a serverless application using the template you just created in Infrastructure Composer, you first need to install the AWS SAM CLI. To do this, follow the instructions in [Installing the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html).

Before you deploy your application, you also need to update the function code that Infrastructure Composer saved along with your template. At the moment, the `lambda_function.py` file that Infrastructure Composer saved contains only the basic 'Hello world' code that Lambda provided when you created the function. 

To update your function code, copy the following code and paste it into the `lambda_function.py` file Infrastructure Composer saved to your local build machine. You specified the directory for Infrastructure Composer to save this file to when you activated Local Sync mode.

This code accepts a key value pair in a message from the Amazon SQS queue you created in Infrastructure Composer. If both the key and value are strings, the code then uses them to write an item to the DynamoDB table defined in your template.

### Updated Python function code


```
import boto3
import os
import json

# define the DynamoDB table that Lambda will connect to
tablename = os.environ['LAMBDAIACTABLE_TABLE_NAME']

# create the DynamoDB resource
dynamo = boto3.client('dynamodb')

def lambda_handler(event, context):
    # get the message out of the SQS event
    message = event['Records'][0]['body']
    data = json.loads(message)
    # write event data to DDB table
    if check_message_format(data):
        key = next(iter(data))
        value = data[key]
        dynamo.put_item(
            TableName=tablename,
            Item={
                'id': {'S': key},
                'Value': {'S': value}
            }
        )
    else:
        raise ValueError("Input data not in the correct format")

# check that the event object contains a single key value  
# pair that can be written to the database
def check_message_format(message):
    if len(message) != 1:
        return False
        
    key, value = next(iter(message.items()))
    
    if not (isinstance(key, str) and isinstance(value, str)):
        return False

    else:
        return True
```

**To deploy your serverless application**

To deploy your application using the AWS SAM CLI, carry out the following steps. For your function to build and deploy correctly, Python version 3.11 must be installed on your build machine and on your `PATH`.

1. Run the following command from the directory in which Infrastructure Composer saved your `template.yaml` and `lambda_function.py` files.

   ```
   sam build
   ```

   This command gathers the build artifacts for your application and places them in the proper format and location to deploy them.

1. To deploy your application and create the Lambda, Amazon SQS, and DynamoDB resources specified in your AWS SAM template, run the following command.

   ```
   sam deploy --guided
   ```

   Using the `--guided` flag means that AWS SAM will show you prompts to guide you through the deployment process. For this deployment, accept the default options by pressing Enter.

During the deployment process, AWS SAM creates the following resources in your AWS account:
+ An CloudFormation [stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html#cfn-concepts-stacks) named `sam-app`
+ A Lambda function with the name format `sam-app-LambdaIaCDemo-99VXPpYQVv1M`
+ An Amazon SQS queue with the name format `sam-app-LambdaIaCQueue-xL87VeKsGiIo`
+ A DynamoDB table with the name format `sam-app-LambdaIaCTable-CN0S66C0VLNV`

AWS SAM also creates the necessary IAM roles and policies so that your Lambda function can read messages from the Amazon SQS queue and perform CRUD operations on the DynamoDB table.

## Testing your deployed application (optional)


To confirm that your serverless application deployed correctly, send a message to your Amazon SQS queue containing a key value pair and check that Lambda writes an item into your DynamoDB table using these values.

**To test your serverless application**

1. Open the [Queues](https://console.aws.amazon.com/sqs/v2/home#/queues) page of the Amazon SQS console and select the queue that AWS SAM created from your template. The name has the format `sam-app-LambdaIaCQueue-xL87VeKsGiIo`.

1. Choose **Send and receive messages** and paste the following JSON into the **Message body** in the **Send message** section.

   ```
   {
       "myKey": "myValue"
   }
   ```

1. Choose **Send message**.

   Sending your message to the queue causes Lambda to invoke your function through the event source mapping defined in your AWS SAM template. To confirm that Lambda has invoked your function as expected, confirm that an item has been added to your DynamoDB table.

1. Open the [Tables](https://console.aws.amazon.com/dynamodbv2#tables) page of the DynamoDB console and select your table. The name has the format `sam-app-LambdaIaCTable-CN0S66C0VLNV`.

1. Choose **Explore table items**. In the **Items returned** pane, you should see an item with the **id** `myKey` and the **Value** `myValue`.

# Deploying Lambda functions with AWS CDK
Using AWS CDK

The AWS Cloud Development Kit (AWS CDK) is an infrastructure as code (IaC) framework that you can use to define AWS cloud infrastructure by using a programming language of your choosing. To define your own cloud infrastructure, you first write an app (in one of the CDK's supported languages) that contains one or more stacks. Then, you synthesize it to an CloudFormation template and deploy your resources to your AWS account. Follow the steps in this topic to deploy a Lambda function that returns an event from an Amazon API Gateway endpoint.

The AWS Construct Library, included with the CDK, provides modules that you can use to model the resources that AWS services provide. For popular services, the library provides curated constructs with smart defaults and best practices. You can use the [aws\$1lambda](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html) module to define your function and supporting resources with just a few lines of code. 

## Prerequisites


Before starting this tutorial, install the AWS CDK by running the following command.

```
npm install -g aws-cdk
```

## Step 1: Set up your AWS CDK project
Step 1: Set up your project

Create a directory for your new AWS CDK app and initialize the project.

------
#### [ JavaScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language javascript
```

------
#### [ TypeScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language typescript
```

------
#### [ Python ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language python
```

After the project starts, activate the project's virtual environment and install the baseline dependencies for AWS CDK.

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

------
#### [ Java ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language java
```

Import this Maven project to your Java integrated development environment (IDE). For example, in Eclipse, choose **File**, **Import**, **Maven**, **Existing Maven Projects**.

------
#### [ C\$1 ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language csharp
```

------

**Note**  
The AWS CDK application template uses the name of the project directory to generate names for source files and classes. In this example, the directory is named `hello-lambda`. If you use a different project directory name, your app won't match these instructions.

AWS CDK v2 includes stable constructs for all AWS services in a single package that's called `aws-cdk-lib`. This package is installed as a dependency when you initialize the project. When working with certain programming languages, the package is installed when you build the project for the first time.

## Step 2: Define the AWS CDK stack
Step 2: Define the stack

A CDK *stack* is a collection of one or more constructs, which define AWS resources. Each CDK stack represents an CloudFormation stack in your CDK app.

To define your CDK stack, follow the instructions for your preferred programming language. This stack defines the following:
+ The function's logical name: `MyFunction`
+ The location of the function code, specified in the `code` property. For more information, see [Handler code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html#handler-code) in the *AWS Cloud Development Kit (AWS CDK) API Reference*.
+ The REST API's logical name: `HelloApi`
+ The API Gateway endpoint's logical name: `ApiGwEndpoint`

Note that all of the CDK stacks in this tutorial use the Node.js [runtime](lambda-runtimes.md) for the Lambda function. You can use different programming languages for the CDK stack and the Lambda function to leverage the strengths of each language. For example, you can use TypeScript for the CDK stack to leverage the benefits of static typing for your infrastructure code. You can use JavaScript for the Lambda function to take advantage of the flexibility and rapid development of a dynamically typed language.

------
#### [ JavaScript ]

Open the `lib/hello-lambda-stack.js` file and replace the contents with the following.

```
const { Stack } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const apigw = require('aws-cdk-lib/aws-apigateway');

class HelloLambdaStack extends Stack {
  /**
   *
   * @param {Construct} scope
   * @param {string} id
   * @param {StackProps=} props
   */
  constructor(scope, id, props) {
    super(scope, id, props);
    const fn = new lambda.Function(this, 'MyFunction', {
      code: lambda.Code.fromAsset('lib/lambda-handler'),
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler'
    });

    const endpoint = new apigw.LambdaRestApi(this, 'MyEndpoint', {
      handler: fn,
      restApiName: "HelloApi"
    });

  }
}

module.exports = { HelloLambdaStack }
```

------
#### [ TypeScript ]

Open the `lib/hello-lambda-stack.ts` file and replace the contents with the following.

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as apigw from "aws-cdk-lib/aws-apigateway";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as path from 'node:path';

export class HelloLambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps){
    super(scope, id, props)
    const fn = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
    });

    const endpoint = new apigw.LambdaRestApi(this, `ApiGwEndpoint`, {
      handler: fn,
      restApiName: `HelloApi`,
    });

  }
}
```

------
#### [ Python ]

Open the `/hello-lambda/hello_lambda/hello_lambda_stack.py` file and replace the contents with the following.

```
from aws_cdk import (
    Stack,
    aws_apigateway as apigw,
    aws_lambda as _lambda
)
from constructs import Construct

class HelloLambdaStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        fn = _lambda.Function(
            self,
            "MyFunction",
            runtime=_lambda.Runtime.NODEJS_LATEST,
            handler="index.handler",
            code=_lambda.Code.from_asset("lib/lambda-handler")
        )

        endpoint = apigw.LambdaRestApi(
            self,
            "ApiGwEndpoint",
            handler=fn,
            rest_api_name="HelloApi"
        )
```

------
#### [ Java ]

Open the `/hello-lambda/src/main/java/com/myorg/HelloLambdaStack.java` file and replace the contents with the following.

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.apigateway.LambdaRestApi;
import software.amazon.awscdk.services.lambda.Function;

public class HelloLambdaStack extends Stack {
    public HelloLambdaStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloLambdaStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Function hello = Function.Builder.create(this, "MyFunction")
                            .runtime(software.amazon.awscdk.services.lambda.Runtime.NODEJS_LATEST)
                            .code(software.amazon.awscdk.services.lambda.Code.fromAsset("lib/lambda-handler"))
                            .handler("index.handler")
                            .build();

        LambdaRestApi api = LambdaRestApi.Builder.create(this, "ApiGwEndpoint")
                                .restApiName("HelloApi")
                                .handler(hello)
                                .build();

    }
}
```

------
#### [ C\$1 ]

Open the `src/HelloLambda/HelloLambdaStack.cs` file and replace the contents with the following.

```
using Amazon.CDK;
using Amazon.CDK.AWS.APIGateway;
using Amazon.CDK.AWS.Lambda;
using Constructs;

namespace HelloLambda
{
    public class HelloLambdaStack : Stack
    {
        internal HelloLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var fn = new Function(this, "MyFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_LATEST,
                Code = Code.FromAsset("lib/lambda-handler"),
                Handler = "index.handler"
            });

            var api = new LambdaRestApi(this, "ApiGwEndpoint", new LambdaRestApiProps
            {
                Handler = fn
            });
        }
    }
}
```

------

## Step 3: Create the Lambda function code
Step 3: Create the function

1. From the root of your project (`hello-lambda`), create the `/lib/lambda-handler` directory for the Lambda function code. This directory is specified in the `code` property of your AWS CDK stack.

1. Create a new file called `index.js` in the `/lib/lambda-handler` directory. Paste the following code into the file. The function extracts specific properties from the API request and returns them as a JSON response.

   ```
   exports.handler = async (event) => {
     // Extract specific properties from the event object
     const { resource, path, httpMethod, headers, queryStringParameters, body } = event;
     const response = {
       resource,
       path,
       httpMethod,
       headers,
       queryStringParameters,
       body,
     };
     return {
       body: JSON.stringify(response, null, 2),
       statusCode: 200,
     };
   };
   ```

## Step 4: Deploy the AWS CDK stack
Step 4: Deploy the stack

1. From the root of your project, run the [cdk synth](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-synth.html) command:

   ```
   cdk synth
   ```

   This command synthesizes an AWS CloudFormation template from your CDK stack. The template is an approximately 400-line YAML file, similar to the following. 
**Note**  
If you get the following error, make sure that you are in the root of your project directory.  

   ```
   --app is required either in command-line, in cdk.json or in ~/.cdk.json
   ```  
**Example CloudFormation template**  

   ```
   Resources:
     MyFunctionServiceRole3C357FF2:
       Type: AWS::IAM::Role
       Properties:
         AssumeRolePolicyDocument:
           Statement:
             - Action: sts:AssumeRole
               Effect: Allow
               Principal:
                 Service: lambda.amazonaws.com
           Version: "2012-10-17"		 	 	 
         ManagedPolicyArns:
           - Fn::Join:
               - ""
               - - "arn:"
                 - Ref: AWS::Partition
                 - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
       Metadata:
         aws:cdk:path: HelloLambdaStack/MyFunction/ServiceRole/Resource
     MyFunction1BAA52E7:
       Type: AWS::Lambda::Function
       Properties:
         Code:
           S3Bucket:
             Fn::Sub: cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}
           S3Key: ab1111111cd32708dc4b83e81a21c296d607ff2cdef00f1d7f48338782f92l3901.zip
         Handler: index.handler
         Role:
           Fn::GetAtt:
             - MyFunctionServiceRole3C357FF2
             - Arn
         Runtime: nodejs24.x
         ...
   ```

1. Run the [cdk deploy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-deploy.html) command:

   ```
   cdk deploy
   ```

   Wait while your resources are created. The final output includes the URL for your API Gateway endpoint. Example:

   ```
   Outputs:
   HelloLambdaStack.ApiGwEndpoint77F417B1 = https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
   ```

## Step 5: Test the function


To invoke the Lambda function, copy the API Gateway endpoint and paste it into a web browser or run a `curl` command:

```
curl -s https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
```

The response is a JSON representation of selected properties from the original event object, which contains information about the request made to the API Gateway endpoint. Example:

```
{
  "resource": "/",
  "path": "/",
  "httpMethod": "GET",
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Accept-Language": "en-US,en;q=0.9",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-ASN": "16509",
    "CloudFront-Viewer-Country": "US",
    "Host": "abcd1234.execute-api.us-east-1.amazonaws.com",
     ...
```

## Step 6: Clean up your resources
Step 6: Clean up

The API Gateway endpoint is publicly accessible. To prevent unexpected charges, run the [cdk destroy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-destroy.html) command to delete the stack and all associated resources.

```
cdk destroy
```

## Next steps


For information about writing AWS CDK apps in your language of choice, see the following:

------
#### [ TypeScript ]

[Working with the AWS CDK in TypeScript](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)

------
#### [ JavaScript ]

[Working with the AWS CDK in JavaScript](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-javascript.html)

------
#### [ Python ]

[Working with the AWS CDK in Python](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html)

------
#### [ Java ]

[Working with the AWS CDK in Java](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-java.html)

------
#### [ C\$1 ]

[Working with the AWS CDK in C\$1](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)

------
#### [ Go ]

[Working with the AWS CDK in Go](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-go.html)

------