Working with layers for TypeScript Lambda functions
A Lambda layer is a .zip file archive that contains supplementary code or data. Layers usually contain library dependencies, a custom runtime, or configuration files. Creating a layer involves three general steps:
-
Package your layer content. This means creating a .zip file archive that contains the dependencies you want to use in your functions.
-
Create the layer in Lambda.
-
Add the layer to your functions.
This topic contains steps and guidance on how to properly package and create a Node.js Lambda layer with external library dependencies. Additionally, this topic explains how use your layer with a function written in TypeScript.
Prerequisites
To follow the steps in this section, you must have the following:
-
Node.js 20
and the npm package manager. For more information about installing Node.js, see Installing Node.js via package manager in the Node.js documentation.
Throughout this topic, we reference the layer-nodejslayer
directory contains the scripts to generate the layer. The application also contains a TypeScript sample
function in the function-ts
directory that uses the dependency from the layer.
After creating a layer, you can transpile, deploy and invoke the corresponding function to verify that everything
works. This document walks through how to create, package, deploy and test this layer using the TypeScript sample function.
This sample application uses the Node.js 20 runtime. If you add additional dependencies to your layer, they must be compatible with Node.js 20.
Node.js layer compatibility with the Lambda runtime environment
When you package code in a Node.js layer, you specify the Lambda runtime environments that the code is compatible with. To assess code compatibility with a runtime, consider what versions of Node.js, what operating systems, and what instruction set architectures the code is designed for.
Lambda Node.js runtimes specify their Node.js version and operating system. In this document, you will use the Node.js
20 runtime, which is based on AL2023. For more information about runtime versions, see Supported runtimes. When you create a Lambda function, you specify the instruction set architecture. In this
document, you will use the arm64
architecture. For more information about architectures in Lambda, see Selecting and configuring an instruction set architecture for your Lambda function.
When you use code provided in a package, each package maintainer independently defines their compatibility. Most Node.js development is designed to work independently of operating system and instruction set architecture. Additionally, breaking incompatibilities with new Node.js versions are not that common. Expect to spend more of your time assessing compatibility between packages than assessing package compatibility with Node.js version, operating system, or instruction set architecture.
Sometimes Node.js packages include compiled code, which require you to consider operating system and
instruction set architecture compatibility. If you do need to assess code compatibility for your packages, you will need to inspect the
packages and their documentation. Packages in NPM can specify their compatibility through the engines
,
os
, and cpu
fields of their package.json
manifest file. For more information
about package.json
files, see package.json
Layer paths for Node.js runtimes
When you add a layer to a function, Lambda loads the layer content into the execution environment. If your layer packages dependencies in specific folder paths, the Node.js execution environment will recognize the modules, and you can reference the modules from your function code.
To ensure that your modules are picked up, package them into your layer .zip file in one of the following folder paths.
These files are stored in /opt
, and the folder paths are loaded into the PATH
environment variable.
nodejs/node_modules
nodejs/node
X
/node_modules
For example, the resulting layer .zip file that you create in this tutorial has the following directory structure:
layer_content.zip
└ nodejs
└ node20
└ node_modules
└ lodash
└ <other potential dependencies>
└ ...
You will put the lodash
nodejs/node20/node_modules
directory. This
ensures that Lambda can locate the library during function invocations.
Packaging the layer content
In this example, you package the lodash
library in a layer .zip file. Complete the following steps
to install and package the layer content.
To install and package your layer content
-
Clone the aws-lambda-developer-guide
repository from GitHub, which contains the sample code that you need in the sample-apps/layer-nodejs
directory.git clone https://github.com/awsdocs/aws-lambda-developer-guide.git
-
Navigate to the
layer
directory of thelayer-nodejs
sample app. This directory contains the scripts that you use to create and package the layer properly.cd aws-lambda-developer-guide/sample-apps/layer-nodejs/layer
-
Ensure the
package.json
file listslodash
. This file defines the dependencies that you want to include in the layer. You can update this file to include any dependencies that you want in your layer.Note
The
package.json
used in this step is not stored or used with your dependencies after they are uploaded to a Lambda layer. It is only used in the layer packaging process, and does not specify a run command and compatibility as the file would in a Node.js application or published package. -
Ensure that you have shell permission to run the scripts in the
layer
directory.chmod 744 1-install.sh && chmod 744 2-package.sh
-
Run the 1-install.sh
script using the following command: ./1-install.sh
This script runs
npm install
, which reads yourpackage.json
and downloads the dependencies defined inside of it.Example 1-install.sh
npm install .
-
Run the 2-package.sh
script using the following command: ./2-package.sh
This script copies the contents from the
node_modules
directory into a new directory namednodejs/node20
. It then zips the contents of thenodejs
directory into a file namedlayer_content.zip
. This is the .zip file for your layer. You can unzip the file and verify that it contains the correct file structure, as shown in the Layer paths for Node.js runtimes section.Example 2-package.sh
mkdir -p nodejs/node20 cp -r node_modules nodejs/node20/ zip -r layer_content.zip nodejs
Creating the layer
Take the layer_content.zip
file that you
generated in the previous section and upload it as a Lambda layer. You can upload a layer using
the AWS Management Console or the Lambda API via the AWS Command Line Interface (AWS CLI). When you upload your layer .zip
file, in the following PublishLayerVersion AWS CLI command, specify
nodejs20.x
as the compatible runtime and arm64
as the compatible
architecture.
aws lambda publish-layer-version --layer-name nodejs-lodash-layer \ --zip-file fileb://layer_content.zip \ --compatible-runtimes nodejs20.x \ --compatible-architectures "arm64"
From the response, note the LayerVersionArn
, which looks like
arn:aws:lambda:us-east-1:
.
You'll need this Amazon Resource Name (ARN) in the next step of this tutorial, when you add
the layer to your function.123456789012
:layer:nodejs-lodash-layer:1
Adding the layer to your function
Deploy a sample Lambda function that uses the lodash
library in its function code, then attach the
layer you created. To create a Lambda function using function code written in TypeScript, you must transpile the
TypeScript to JavaScript for use by the Node.js runtime. For more information about this process, see Define Lambda function handler in TypeScript. For better compatibility, use tsc to transpile your TypeScript module when you
distribute your dependencies with layers. If you bundle your dependencies, consider using esbuild. For more
information about bundling with esbuild, see Deploy transpiled TypeScript code in Lambda with .zip file archives.
To deploy the function, you need an execution role. For more information, see Defining Lambda function permissions with an execution role. If you don't have an existing execution role, follow the steps in the collapsible section. Otherwise, skip to the next section to deploy the function.
To create an execution role
-
Open the roles page
in the IAM console. -
Choose Create role.
-
Create a role with the following properties.
-
Trusted entity – Lambda.
-
Permissions – AWSLambdaBasicExecutionRole.
-
Role name –
lambda-role
.
The AWSLambdaBasicExecutionRole policy has the permissions that the function needs to write logs to CloudWatch Logs.
-
The sample function code_.findLastIndex
method to read through an array of objects. It
compares the objects against a criteria to find the index of a match. Then, it returns the index and value of the
object in the Lambda response.
import { Handler } from 'aws-lambda'; import * as _ from 'lodash'; type User = { user: string; active: boolean; } type UserResult = { statusCode: number; body: string; } const users: User[] = [ { 'user': 'Carlos', 'active': true }, { 'user': 'Gil-dong', 'active': false }, { 'user': 'Pat', 'active': false } ]; export const handler: Handler<any, UserResult> = async (): Promise<UserResult> => { let out = _.findLastIndex(users, (user: User) => { return user.user == 'Pat'; }); const response = { statusCode: 200, body: JSON.stringify(out + ", " + users[out].user), }; return response; };
To deploy the Lambda function
-
Navigate to the
function-ts/
directory of thelayer-nodejs
sample application. If you're currently in thelayer/
directory of thelayer-nodejs
sample application, then run the following command:cd ../function-ts
-
Install the development dependencies listed in the
package.json
using the following command:npm install
-
Run the
build
task defined in thepackage.json
to transpile and package your function code into a .zip file. Use the following command:npm run build
-
Deploy the function. In the following AWS CLI command, replace the
--role
parameter with your execution role ARN:aws lambda create-function --function-name nodejs_function_with_layer \ --runtime nodejs20.x \ --architectures "arm64" \ --handler index.handler \ --role
arn:aws:iam::123456789012:role/lambda-role
\ --zip-file fileb://dist/index.zip -
Attach the layer to your function. In the following AWS CLI command, replace the
--layers
parameter with the layer version ARN that you noted earlier:aws lambda update-function-configuration --function-name nodejs_function_with_layer \ --cli-binary-format raw-in-base64-out \ --layers "
arn:aws:lambda:us-east-1:123456789012:layer:nodejs-lodash-layer:1
" -
Invoke your function to verify it works using the following AWS CLI command:
aws lambda invoke --function-name nodejs_function_with_layer \ --cli-binary-format raw-in-base64-out \ --payload '{}' response.json
You should see output that looks like this:
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" }
The output
response.json
file contains details about the response.
You can now delete the resources that you created for this tutorial, unless you want to retain them. By deleting AWS resources that you're no longer using, you prevent unnecessary charges to your AWS account.
To delete the Lambda layer
-
Open the Layers page
of the Lambda console. -
Select the layer that you created.
-
Choose Delete, then choose Delete again.
To delete the Lambda function
-
Open the Functions page
of the Lambda console. -
Select the function that you created.
-
Choose Actions, Delete.
-
Type
delete
in the text input field and choose Delete.