Deploy a Lambda Function in Node.js with AWS CDK v2
The AWS CDK is a tool that makes it easy to create your infrastructure through the code. Before, we used CloudFormation or the AWS console to create our infrastructure. Using these paths has some drawbacks:
- The CloudFormation is hard to read and navigate.
- There is no way to use computed or dynamic expressions.
- When using the console, you don't have the history of our changes on the infrastructure.
- It is impossible to share the configuration since there is no way to update the changes applied.
The AWS CDK solves these issues in an elegant way: the ability to describe your infrastructure as a code using your favorite programming language.
Currently, at the time I'm writing this, it supports TypeScript, JavaScript, Python, Java, C#, and Go.
The source can be versioned in Git to keep the history of changes applied.
This tutorial will show how to create a Lambda Function with the AWS CDK v2 and deploy it in production.
Prerequisites
To achieve this, here are some elements required:
- An AWS account; a free tier is enough.
- AWS CLI configured; check out my tutorial to do that
- Node.js 18+ and NPM - Download link.
Install the CDK globally
We need to install the Node.js package to use the CDK commands through the CLI. It will be helpful to perform tasks such as:
- Generate a new AWS CDK project that will define our infrastructure.
- Generate the CloudFormation template from the TypeScript code.
- Build and deploy the infrastructure AWS.
Run the command to globally install the AWS CDK version 2:
npm install -g cdk
Check if the installation succeeded by running: cdk --version
Create the project with AWS CDK v2
Now, create a folder that will hold the source code of our project.
mkdir lambda-node-cdk
cd lambda-node-cdk
Initialize a blank AWS CDK project by running the command below:
cdk init --language typescript
The command will generate many files and install the necessary Node.js dependencies required. Below is the project structure:
This is a classic minimal Node.js project with TypeScript, but there are some files to focus on:
lib/lambda-node-cdk-stack.ts
is where your CDK application's main stack is defined. This is the file we'll be spending most of our time in.bin/lambda-node-cdk.ts
It is the entry point of the CDK application. It will load the stack defined inlib/lambda-node-cdk-stack.ts
.test/lambda-node-cdk.test.ts
is where we write tests for our stack defined inlib/lambda-node-cdk-stack
.cdk.json
file tells the toolkit on how to run your app. In our case, it will benpx ts-node bin/lambda-node-cdk.ts
.
We will focus on the lib/lambda-node-cdk.ts file to create our Lambda Function.
Create the Lambda Function with AWS CDK v2
The AWS CDK v2 provides a single Node.js package named aws-cdk-lib to define the infrastructure of most AWS services in TypeScript.
Importing methods related to an AWS service follows this pattern:
import * as service from 'aws-cdk-lib/aws-<service>';
Here are some examples:
- For AWS Lambda:
import * as lambda from aws-cdk-lib/aws-lambda
- For AWS SQS:
import * as sqs from aws-cdk-lib/aws-sqs
- For AWS S3:
import * as s3 from aws-cdk-lib/aws-s3
Update the file lib/lambda-node-cdk.ts to create the Lambda Function with the required properties:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class LambdaNodeCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new lambda.Function(this, 'LambdaNodeStack', {
code: lambda.Code.fromAsset('./src'),
functionName: "lambdaNode",
handler: 'index.handler',
memorySize: 1024,
runtime: lambda.Runtime.NODEJS_18_X,
timeout: cdk.Duration.seconds(300),
});
}
}
Let's explain what we did here:
- We create a Lambda Function called
lambdaNode
Running on Node.js 18 with 1GB of memory allocated. - The time-out is set to 300 seconds, which is equal to 5 minutes.
- The property "code" indicates the folder's path to find the code to run when the Lambda is triggered. It is located in the "src" folder at the project root. It doesn't exist yet.
- The property "handler" indicates the entry file and then the function name executed in this file. So the value
index.handler
can be broken down into:- index: the file called
index.js
inside thesrc
directory. - handler: the function inside the
index.js
to execute.
- index: the file called
Write the code to execute by the Lambda Function
In the infrastructure defined earlier, expect to find the code to execute in the "src" folder in a file named "index.js"; let's create them with the code below:
mkdir src
touch src/index.js
Open the file index.js and add the content below:
exports.handler = async function(event) {
return {
statusCode: 200,
headers: { "Content-Type": "text/json" },
body: JSON.stringify({ message: "Hello from my Lambda node!" })
};
};
When we will trigger the Lambda function, it will respond with the message:
{ "message": "Hello from my Lambda node!" }
Deploy the Lambda Function on AWS
The first step to deploying Lambda Function is to generate the CloudFormation template from the AWS CDK code. It will also check if there is no error in the stack definition and throw an error if it is the case.
Run the command below to do that:
cdk synth
This command will output the CloudFormation stack to be created in the console and generate a folder named "cdk.out" containing the template and the assets files.
Bootstrap the deployment environment on AWS
This action creates a CloudFormation stack that includes resources used for the toolkit's operation, like an S3 bucket to store templates and assets during deployment.
It is required to run only if it is the first time you deploy with the AWS CDK on an AWS account, so you can skip this if you have already done it.
Run the command below to bootstrap the environment:
cdk bootstrap
⏳ Bootstrapping environment aws://123456789012/eu-west-1...
Once done, we can deploy our project with the command below:
cdk deploy
You will have the output below; press the touch y
to continue...
Wait for the process to complete, then go to the AWS console to test your lambda function.
We see our lambda function; click on the Function name to go to the detail page.
Click on the "Test" button to trigger the Lambda Function. You will see the execution result on the page.
You have successfully deployed a Lambda Function with the AWS CDK v2.
Test the Lambda Function with the Function URL
In April 2022, AWS announced an interesting feature for Lambda Function called Function URL, a built-in HTTPS endpoint for a Lambda Function.
With this feature, when you deploy a Lambda Function on AWS, a URL is generated to trigger the Lambda Function through HTTP. This makes it easier to test your Function without going through multiple clicks in the AWS console.
The feature is disabled by default, so you must configure it; since we defined our Lambda Function with the AWS CDK, let's update it to configure the Function URL.
Update the code of the file lib/lambda-node-cdk.ts with the code below:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class LambdaNodeCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const lambdaFunction = new lambda.Function(this, 'LambdaNodeStack', {
code: lambda.Code.fromAsset('./src'),
functionName: "lambdaNode",
handler: 'index.handler',
memorySize: 1024,
runtime: lambda.Runtime.NODEJS_18_X,
timeout: cdk.Duration.seconds(300),
});
const lambdaFunctionUrl = lambdaFunction.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
invokeMode: lambda.InvokeMode.BUFFERED,
});
new cdk.CfnOutput(this, 'LambdaNodeUrl', {
value: lambdaFunctionUrl.url,
});
}
}
In the instance of our Lambda Function definition, we call the method addFunctionUrl()
with two options:
- authType: is the authentication mode authorizing/blocking the caller to invoke the Lambda Function; we set it to "NONE" so anyone having the Function URL can invoke it.
- invokeMode: is how our Lambda Function will return the response, which can be buffered or a stream.
Let's deploy the code on AWS by running the command below:
cdk synth
cdk deploy
We can see the new changes to apply to our Lambda Function in the Function URL. Once deployed, the URL is printed in the terminal:
Copy the Lambda Function URL, open the browser tab, and paste it. You get the following output in your browser:
Test the Lambda Function locally
We tested our Lambda Function in production, but in a classic software development lifecycle, we usually test the Lambda Function locally before deploying it in production.
To do it with the AWS CDK, we will use the AWS SAM CLI.
The AWS SAM CLI provides a command to invoke the Lambda Function locally. Follow the AWS documentation guide to install it on your computer.
You will need Docker running on your computer because the SAM will pull the Docker image of Node.js 18 for the Lambda Function in the ECR repository.
Pulling an image from the public ECR repository requires an authentication; run the command below to authenticate:
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
The syntax to invoke the Lambda Function defined with the AWS CDK is the following:
sam local invoke -t <CloudFormationTemplate> <FunctionStackName>
- <CloudFormationTemplate>: is the path to the CloudFormation template of the stack, which is generated in the folder "cdk.out" after executing the command
cdk synth
. - <FunctionStackName>: is the name of your Lambda Function stack you set in the file
lib/lambda-node-cdk-stack.ts
.
Run the command below to invoke your Lambda Function with SAM CLI:
cdk synth
sam local invoke -t ./cdk.out/LambdaNodeCdkStack.template.json LambdaNodeStack
We get the output below:
You can now test your function locally before deploying it in production.
Wrap up
Deploying a Lambda Function with AWS CDK can be summarized in the following steps:
- Generate the AWS CDK project.
- Write the code of your infrastructure in TypeScript.
- Synthesize the infrastructure code to generate the CloudFormation template.
- Deploy the resources on AWS.
We deployed a Lambda Function returning a simple message when invoked, but you can go further by building a Backend API with the AWS CDK, as I show in this tutorial.
Find the final code source on the GitHub Repository.
Follow me on Twitter or subscribe to my newsletter to avoid missing the upcoming posts and the tips and tricks I occasionally share.