Write TypeScript Lambda functions in AWS CDK - Complete Guide

Borislav Hadzhiev

Last updated: Jan 27, 2024
4 min


# Table of Contents

  1. Writing the Infrastructure for TypeScript Lambdas in AWS CDK
  2. Writing the Code for TypeScript Lambdas
  3. Deploying TypeScript Lambdas with AWS CDK
  4. Optimizing TypeScript Lambdas with CDK
  5. Discussion

# Writing the Infrastructure for TypeScript Lambdas in AWS CDK

We write our CDK code using TypeScript, so it makes sense to also write our Lambda code in TypeScript.

Nodejs doesn't natively support TypeScript, so we have to first compile our TypeScript code to JavaScript before we can deploy our Lambda functions.

In order to write a Lambda function in TypeScript and provision it with CDK, we have to use the NodejsFunction construct, which uses esbuild to automatically transpile and bundle our code.

The code for this article is available on GitHub

Let's define the infrastructure for our function using CDK.

import * as cdk from 'aws-cdk-lib'; import {NodejsFunction} from 'aws-cdk-lib/aws-lambda-nodejs'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as path from 'path'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const myFunction = new NodejsFunction(this, 'my-function', { memorySize: 1024, timeout: cdk.Duration.seconds(5), runtime: lambda.Runtime.NODEJS_18_X, handler: 'main', entry: path.join(__dirname, `/../src/my-lambda/index.ts`), }); } }
If you still use CDK version 1, switch to the cdk-v1 branch in the GitHub repository.

Let's go over the code:

  • We have a CDK stack that provisions a single Lambda function.

  • The Lambda function uses the NodejsFunction construct which automatically transpiles and bundles our code, regardless if it's written in JavaScript or TypeScript.

  • The entry prop we passed to the function constructor is a path to the Lambda function's code on the local file system. The entry prop supports files with .js, .jsx, .ts and .tsx extensions.

  • The other props we passed to the NodejsFunction constructor are the same props the generic Function construct supports.

# Writing the Code for TypeScript Lambdas

In order to avoid unnecessary distractions, our function code will be very simple.

import {APIGatewayProxyEventV2, APIGatewayProxyResultV2} from 'aws-lambda'; export async function main( event: APIGatewayProxyEventV2, ): Promise<APIGatewayProxyResultV2> { console.log('event ๐Ÿ‘‰', event); return { body: JSON.stringify({message: 'Successful lambda invocation'}), statusCode: 200, }; }

We defined a simple lambda function, in which we've typed the event and the response.

# Deploying TypeScript Lambdas with AWS CDK

Our CDK code gets compiled down to CloudFormation before a deployment.

When we synthesize our CloudFormation stack, it gets generated in the cdk.out directory. This is also where the asset files for our Lambda functions are stored.

Let's run the synth command to generate the Lambda assets.

npx aws-cdk synth

If we now take a look at the assets folder in the cdk.out directory, we can see that our Lambda function's code has been compiled down to JavaScript.

cdk out lambda

At this point, we are ready to deploy our stack.

npx aws-cdk deploy

Now that the Lambda function has been successfully deployed, we can run a quick test using the Lambda console.

lambda invoked

At this point, we've successfully invoked a Lambda function that we wrote using TypeScript and provisioned via AWS CDK.

# Optimizing TypeScript Lambdas with CDK

The NodejsFunction construct uses esbuild under the hood to automatically transpile and bundle our code.

We can use the construct to write JavaScript or TypeScript and everything just works automatically. There are no Webpack configuration files we have to manage.

We can reduce the bundle size of our Lambda functions by setting the minify property to true in the props object of the NodejsFunction.

const myFunction = new NodejsFunction(this, 'my-function', { // ...rest // ๐Ÿ‘‡ bundling: { minify: true, externalModules: ['aws-sdk'], }, });
The code for this article is available on GitHub

We've set the minify and externalModules options on the bundling, property:

  • minify is a boolean that allows us to specify whether we want to minify the code of our Lambda function. This enables us to decrease bundle size and improve performance for larger functions.

  • externalModules is a string array that allows us to specify which modules should NOT be bundled with our Lambda code. This enables us to exclude modules that are already available in the Lambda runtime - for instance aws-sdk and layers.

    For example, if you used an npm package called yup as a Lambda layer, you would add the string yup to the externalModules array because layers are already available in the Lambda environment.

I'll now run the synth command to inspect the output.

npx aws-cdk synth

If I open the cdk.out directory and look at the lambda asset, we can see that it has been minified and is a one-liner.

lambda minified

# Discussion

The esbuild library is written in Golang and is way faster than any other bundler I've ever used, so deployments for medium-sized projects go relatively quick. Look at the speed comparison to other bundlers.

The best thing about this approach is that we don't have to manage Webpack configurations and have our dependencies break every 2-3 months.

# Cleanup

To delete the stack from your account, run the destroy command.

npx aws-cdk destroy

# Outro

We managed to use esbuild to write Lambda functions in Typescript. Now all of our code, including the infrastructure, is written using the same language.

The code for this article is available on GitHub

I've also written an article on how to provision lambda functions in CDK without using TypeScript.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev