TIL: You can bundle lambdas with CDK rather than uploading a zip


Whenever I needed to create a lambda function within a repo where everything is being deployed by the AWS CDK I would do something like this:

  1. Use a shell script to build the lambda function and add its dependencies into a deployment directory.
  2. Package it into a .zip file - zip -r deployment.zip deployment.
  3. Use something like the CDK code below to deploy the .zip to a lambda function.
import * as lambda from 'aws-cdk-lib/aws-lambda';

const myLambda = new lambda.Function(
  this,
  'MyLambda',
  {
    code: lambda.Code.fromAsset(
      path.join(__dirname, 'deployment.zip'),
    ),
    handler: 'deployment/index.handler',
    runtime: lambda.Runtime.NODEJS_22_X,
    ...
  },
);

The process of generating the .zip file is annoying and adds an extra step to the build and deployment pipeline. There’s also a size limit on the final file which can be uploaded which can sometimes cause problems if you’re in the unfortunate position of needing to add some heavier dependencies like prisma. Overall, it’s not ideal but it was sufficient.

However, I’ve recently come across the NodeJsFunction construct which makes this process significantly simpler. The new process doesn’t require any additional build steps, you can simply allow your code to be built and bundled by AWS. Here’s how you would tweak the CDK code:

import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';

const myLambda = new lambdaNodeJs.NodeJsFunction(
  this,
  'MyLambda',
  {
    bundling: {
	  externalModules: [],
    },
    depsLockFilePath: path.join(__dirname, '..', 'yarn.lock'),
    entry: path.join(__dirname, '..', 'lambda', 'index.ts'),
    projectRoot: path.join(__dirname, '..'),
    handler: 'deployment/index.handler',
    runtime: lambda.Runtime.NODEJS_22_X,
    ...
  },
);

WARNING

Note at the time of writing Currently you also need to specify the version of esbuild to use because there’s a bug with the cdk implementation. See this issue for more information.

{
  ...
  bundling: {
    esbuildVersion: '0.21.5',
  },
}