This is the AWS CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023.
Tutorial: Create a serverless Hello World application
In this tutorial, you use the AWS Cloud Development Kit (AWS CDK) to create a simple serverless Hello World application that implements a basic API backend consisting of the following:
-
Amazon API Gateway REST API – Provides an HTTP endpoint that is used to invoke your function through an HTTP GET request.
-
AWS Lambda function – Function that returns a
Hello World!
message when invoked with the HTTP endpoint. -
Integrations and permissions – Configuration details and permissions for your resources to interact with one another and perform actions, such as writing logs to Amazon CloudWatch.
The following diagram shows the components of this application:
![Diagram of a Lambda function that is invoked when you send a GET request to the API Gateway endpoint.](/images/cdk/v2/guide/images/serverless-example-01.png)
For this tutorial, you will create and interact with your application in the following steps:
-
Create an AWS CDK project.
-
Define a Lambda function and API Gateway REST API using L2 constructs from the AWS Construct Library.
-
Deploy your application to the AWS Cloud.
-
Interact with your application in the AWS Cloud.
-
Delete the sample application from the AWS Cloud.
Topics
Prerequisites
Before starting this tutorial, complete the following:
-
Create an AWS account and have the AWS Command Line Interface (AWS CLI) installed and configured.
-
Install Node.js and npm.
-
Install the CDK Toolkit globally, using
npm install -g aws-cdk
.
For more information, see Getting started with the AWS CDK.
We also recommend a basic understanding of the following:
-
What is the AWS CDK? for a basic introduction to the AWS CDK.
-
Learn AWS CDK core concepts for an overview of core concepts of the AWS CDK.
Step 1: Create a CDK project
In this step, you create a new CDK project using the AWS CDK CLI
cdk init
command.
To create a CDK project
-
From a starting directory of your choice, create and navigate to a project directory named
cdk-hello-world
on your machine:$
mkdir cdk-hello-world && cd cdk-hello-world
-
Use the
cdk init
command to create a new project in your preferred programming language:The CDK CLI creates a project with the following structure:
The CDK CLI automatically creates a CDK app that contains a single stack. The
CDK app instance is created from the App
class. The following is a portion of your CDK
application file:
Step 2: Create your Lambda function
Within your CDK project, create a lambda
directory that includes a new
hello.js
file. The following is an example:
Note
To keep this tutorial simple, we use a JavaScript Lambda function for all CDK programming languages.
Define your Lambda function by adding the following to the newly created file:
exports.handler = async (event) => { return { statusCode: 200, headers: { "Content-Type": "text/plain" }, body: JSON.stringify({ message: "Hello, World!" }), }; };
Step 3: Define your constructs
In this step, you will define your Lambda and API Gateway resources using AWS CDK L2 constructs.
Open the project file that defines your CDK stack. You will modify this file to define your constructs. The following is an example of your starting stack file:
In this file, the AWS CDK is doing the following:
-
Your CDK stack instance is instantiated from the
Stack
class. -
The
Constructs
base class is imported and provided as the scope or parent of your stack instance.
Define your Lambda function resource
To define your Lambda function resource, you import and use the aws-lambda
L2 construct from the
AWS Construct Library.
Modify your stack file as follows:
Here, you create a Lambda function resource and define the following properties:
-
runtime
– The environment the function runs in. Here, we use Node.js version 20.x. -
code
– The path to the function code on your local machine. -
handler
– The name of the specific file that contains your function code.
Define your API Gateway REST API resource
To define your API Gateway REST API resource, you import and use the aws-apigateway
L2 construct from the
AWS Construct Library.
Modify your stack file as follows:
Here, you create an API Gateway REST API resource, along with the following:
-
An integration between the REST API and your Lambda function, allowing the API to invoke your function. This includes the creation of a Lambda permission resource.
-
A new resource or path named
hello
that is added to the root of the API endpoint. This creates a new endpoint that adds/hello
to your base URL. -
A GET method for the
hello
resource. When a GET request is sent to the/hello
endpoint, the Lambda function is invoked and its response is returned.
Step 4: Prepare your application for deployment
In this step you prepare your application for deployment by building, if necessary, and performing basic validation
with the AWS CDK CLI
cdk synth
command.
If necessary, build your application:
Run cdk synth
to synthesize an AWS CloudFormation template from your CDK code. By using L2 constructs,
many of the configuration details required by AWS CloudFormation to facilitate the interaction between your Lambda function and
REST API are provisioned for you by the AWS CDK.
From the root of your project, run the following:
$
cdk synth
Note
If you receive an error like the following, verify that you are in the cdk-hello-world
directory and try again:
--app is required either in command-line, in cdk.json or in ~/.cdk.json
If successful, the AWS CDK CLI will output the AWS CloudFormation template in YAML format at the
command prompt. A JSON formatted template is also saved in the cdk.out
directory.
The following is an example output of the AWS CloudFormation template:
Resources: HelloWorldFunctionServiceRole
unique-identifier
: 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: CdkHelloWorldStack/HelloWorldFunction/ServiceRole/Resource HelloWorldFunctionunique-identifier
: Type: AWS::Lambda::Function Properties: Code: S3Bucket: Fn::Sub: cdk-unique-identifier
-assets-${AWS::AccountId}-${AWS::Region} S3Key:unique-identifier
.zip Handler: hello.handler Role: Fn::GetAtt: - HelloWorldFunctionServiceRoleunique-identifier
- Arn Runtime: nodejs20.x DependsOn: - HelloWorldFunctionServiceRoleunique-identifier
Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldFunction/Resource aws:asset:path: asset.unique-identifier
aws:asset:is-bundled: false aws:asset:property: Code HelloWorldApiunique-identifier
: Type: AWS::ApiGateway::RestApi Properties: Name: HelloWorldApi Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Resource HelloWorldApiDeploymentunique-identifier
: Type: AWS::ApiGateway::Deployment Properties: Description: Automatically created by the RestApi construct RestApiId: Ref: HelloWorldApiunique-identifier
DependsOn: - HelloWorldApihelloGETunique-identifier
- HelloWorldApihellounique-identifier
Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Deployment/Resource HelloWorldApiDeploymentStageprod012345ABC
: Type: AWS::ApiGateway::Stage Properties: DeploymentId: Ref: HelloWorldApiDeploymentunique-identifier
RestApiId: Ref: HelloWorldApiunique-identifier
StageName: prod Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/DeploymentStage.prod/Resource HelloWorldApihellounique-identifier
: Type: AWS::ApiGateway::Resource Properties: ParentId: Fn::GetAtt: - HelloWorldApiunique-identifier
- RootResourceId PathPart: hello RestApiId: Ref: HelloWorldApiunique-identifier
Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/Resource HelloWorldApihelloGETApiPermissionCdkHelloWorldStackHelloWorldApiunique-identifier
: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: Fn::GetAtt: - HelloWorldFunctionunique-identifier
- Arn Principal: apigateway.amazonaws.com SourceArn: Fn::Join: - "" - - "arn:" - Ref: AWS::Partition - ":execute-api:" - Ref: AWS::Region - ":" - Ref: AWS::AccountId - ":" - Ref: HelloWorldApi9E278160 - / - Ref: HelloWorldApiDeploymentStageprodunique-identifier
- /GET/hello Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.CdkHelloWorldStackHelloWorldApiunique-identifier
.GET..hello HelloWorldApihelloGETApiPermissionTestCdkHelloWorldStackHelloWorldApiunique-identifier
: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: Fn::GetAtt: - HelloWorldFunctionunique-identifier
- Arn Principal: apigateway.amazonaws.com SourceArn: Fn::Join: - "" - - "arn:" - Ref: AWS::Partition - ":execute-api:" - Ref: AWS::Region - ":" - Ref: AWS::AccountId - ":" - Ref: HelloWorldApiunique-identifier
- /test-invoke-stage/GET/hello Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/ApiPermission.Test.CdkHelloWorldStackHelloWorldApiunique-identifier
.GET..hello HelloWorldApihelloGETunique-identifier
: Type: AWS::ApiGateway::Method Properties: AuthorizationType: NONE HttpMethod: GET Integration: IntegrationHttpMethod: POST Type: AWS_PROXY Uri: Fn::Join: - "" - - "arn:" - Ref: AWS::Partition - ":apigateway:" - Ref: AWS::Region - :lambda:path/2015-03-31/functions/ - Fn::GetAtt: - HelloWorldFunctionunique-identifier
- Arn - /invocations ResourceId: Ref: HelloWorldApihellounique-identifier
RestApiId: Ref: HelloWorldApiunique-identifier
Metadata: aws:cdk:path: CdkHelloWorldStack/HelloWorldApi/Default/hello/GET/Resource CDKMetadata: Type: AWS::CDK::Metadata Properties: Analytics: v2:deflate64:unique-identifier
Metadata: aws:cdk:path: CdkHelloWorldStack/CDKMetadata/Default Condition: CDKMetadataAvailable Outputs: HelloWorldApiEndpointunique-identifier
: Value: Fn::Join: - "" - - https:// - Ref: HelloWorldApiunique-identifier
- .execute-api. - Ref: AWS::Region - "." - Ref: AWS::URLSuffix - / - Ref: HelloWorldApiDeploymentStageprodunique-identifier
- / Conditions: CDKMetadataAvailable: Fn::Or: - Fn::Or: - Fn::Equals: - Ref: AWS::Region - af-south-1 - Fn::Equals: - Ref: AWS::Region - ap-east-1 - Fn::Equals: - Ref: AWS::Region - ap-northeast-1 - Fn::Equals: - Ref: AWS::Region - ap-northeast-2 - Fn::Equals: - Ref: AWS::Region - ap-south-1 - Fn::Equals: - Ref: AWS::Region - ap-southeast-1 - Fn::Equals: - Ref: AWS::Region - ap-southeast-2 - Fn::Equals: - Ref: AWS::Region - ca-central-1 - Fn::Equals: - Ref: AWS::Region - cn-north-1 - Fn::Equals: - Ref: AWS::Region - cn-northwest-1 - Fn::Or: - Fn::Equals: - Ref: AWS::Region - eu-central-1 - Fn::Equals: - Ref: AWS::Region - eu-north-1 - Fn::Equals: - Ref: AWS::Region - eu-south-1 - Fn::Equals: - Ref: AWS::Region - eu-west-1 - Fn::Equals: - Ref: AWS::Region - eu-west-2 - Fn::Equals: - Ref: AWS::Region - eu-west-3 - Fn::Equals: - Ref: AWS::Region - il-central-1 - Fn::Equals: - Ref: AWS::Region - me-central-1 - Fn::Equals: - Ref: AWS::Region - me-south-1 - Fn::Equals: - Ref: AWS::Region - sa-east-1 - Fn::Or: - Fn::Equals: - Ref: AWS::Region - us-east-1 - Fn::Equals: - Ref: AWS::Region - us-east-2 - Fn::Equals: - Ref: AWS::Region - us-west-1 - Fn::Equals: - Ref: AWS::Region - us-west-2 Parameters: BootstrapVersion: Type: AWS::SSM::Parameter::Value<String> Default: /cdk-bootstrap/hnb659fds/version Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip] Rules: CheckBootstrapVersion: Assertions: - Assert: Fn::Not: - Fn::Contains: - - "1" - "2" - "3" - "4" - "5" - Ref: BootstrapVersion AssertDescription: CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.
By using L2 constructs, you define a few properties to configure your resources and use helper methods to integrate them together. The AWS CDK configures the majority of your AWS CloudFormation resources and properties required to provision your application.
Step 5: Deploy your application
In this step, you use the AWS CDK CLI
cdk deploy
command to deploy your application. The AWS CDK works with the AWS CloudFormation service to provision your
resources.
Important
You must perform a one-time bootstrapping of your AWS environment before deployment. For instructions, see Bootstrap your environment.
From the root of your project, run the following. Confirm changes if prompted:
$
cdk deploy
✨ Synthesis time: 2.44s ... Do you wish to deploy these changes (y/n)?y
When deployment completes, the AWS CDK CLI will output your endpoint URL. Copy this URL for the next step. The following is an example:
... ✅ HelloWorldStack ✨ Deployment time: 45.37s Outputs: HelloWorldStack.HelloWorldApiEndpoint
unique-identifier
= https://<api-id>
.execute-api.<region>
.amazonaws.com/prod/ Stack ARN: arn:aws:cloudformation:region
:account-id
:stack/HelloWorldStack/unique-identifier
...
Step 6: Interact with your application
In this step, you initiate a GET request to your API endpoint and receive your Lambda function response.
Locate your endpoint URL from the previous step and add the /hello
path. Then, using your browser or
command prompt, send a GET request to your endpoint. The following is an example:
$
curl https://
{"message":"Hello World!"}%<api-id>
.execute-api.<region>
.amazonaws.com/prod/hello
Congratulations, you have successfully created, deployed, and interacted with your application using the AWS CDK!
Step 7: Delete your application
In this step, you use the AWS CDK CLI to delete your application from the AWS Cloud.
To delete your application, run cdk destroy
. When prompted, confirm your request to delete the
application:
$
cdk destroy
Are you sure you want to delete: CdkHelloWorldStack (y/n)?y
CdkHelloWorldStack: destroying... [1/1] ... ✅ CdkHelloWorldStack: destroyed
Troubleshooting
Error: {“message”: “Internal server error”}%
When invoking the deployed Lambda function, you receive this error. This error could occur for multiple reasons.
To troubleshoot further
Use the AWS CLI to invoke your Lambda function.
-
Modify your stack file to capture the output value of your deployed Lambda function name. The following is an example:
... class CdkHelloWorldStack extends Stack { constructor(scope, id, props) { super(scope, id, props); // Define the Lambda function resource // ... new CfnOutput(this, 'HelloWorldFunctionName', { value: helloWorldFunction.functionName, description: 'JavaScript Lambda function' }); // Define the API Gateway resource // ...
-
Deploy your application again. The AWS CDK CLI will output the value of your deployed Lambda function name:
$
cdk deploy
✨ Synthesis time: 0.29s ... ✅ CdkHelloWorldStack ✨ Deployment time: 20.36s Outputs: ... CdkHelloWorldStack.HelloWorldFunctionName = CdkHelloWorldStack-HelloWorldFunctionunique-identifier
... -
Use the AWS CLI to invoke your Lambda function in the AWS Cloud and output the response to a text file:
$
aws lambda invoke --function-name CdkHelloWorldStack-HelloWorldFunction
unique-identifier
output.txt -
Check
output.txt
to see your results.
- Possible cause: API Gateway resource is defined incorrectly in your stack file.
-
If
output.txt
shows a successful Lambda function response, the issue could be with how you defined your API Gateway REST API. The AWS CLI invokes your Lambda directly, not through your endpoint. Check your code to ensure it matches this tutorial. Then, deploy again. - Possible cause: Lambda resource is defined incorrectly in your stack file.
-
If
output.txt
returns an error, the issue could be with how you defined your Lambda function. Check your code to ensure it matches this tutorial. Then deploy again.