Creating and Using Lambda Layers with AWS SAM and Node.js

As your Lambda functions grow, youβll want to avoid duplicating code or dependencies across functions. AWS Lambda Layers solve this by letting you package shared code (like libraries or utilities) once and reuse them across multiple Lambdas.
In this post, youβll learn:
-
How to create a custom Lambda Layer with AWS SAM using Node.js
-
How to bundle it with esbuild using a Makefile
-
How to use AWS Lambda Powertools for TypeScript as a global logging layer
What is a Lambda Layer?
A Lambda Layer is a ZIP archive containing libraries, a runtime, or other dependencies. Itβs extracted to the /opt
directory in the Lambda runtime, making it perfect for sharing utility code or dependencies across functions.
Step 1: Create a Layer in Your SAM Project
Letβs create a utility layer (e.g., utils) to share code.
Directory structure:
my-sam-app/
βββ layers/
β βββ utils/
β βββ utils.js
β βββ package.json
β βββ tsconfig.json
β βββ Makefile
Your utils.js
could be something like:
export const greet = (name: string) => {
return `Hello, ${name}!`;
};
Step 2: Use a Makefile with esbuild
The tsconfig.json
:
{
"compilerOptions": {
"strict": true,
"target": "es2023",
"preserveConstEnums": true,
"resolveJsonModule": true,
"noEmit": false,
"sourceMap": false,
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./utils"
},
"exclude": ["node_modules", "**/*.test.ts"]
}
Create a Makefile
inside the utils/
folder:
build-Utils:
npm install
npm run build
mkdir -p "$(ARTIFACTS_DIR)/nodejs/node_modules"
cp package.json package-lock.json "$(ARTIFACTS_DIR)/nodejs/" # for runtime deps
npm install --omit=dev --prefix "$(ARTIFACTS_DIR)/nodejs/" # for runtime deps
rm "$(ARTIFACTS_DIR)/nodejs/package.json" # for runtime deps
cp -r utils "$(ARTIFACTS_DIR)/nodejs/node_modules"
SAM will automatically pick this up when you run sam build
.
Step 3: Define the Layer in template.yml
Resources:
UtilsLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: utils-layer
Description: Common utility functions
ContentUri: layers/utils
CompatibleRuntimes:
- nodejs22.x
RetentionPolicy: Retain
Metadata:
BuildMethod: makefile
Step 3: Attach Layer to Lambda Function
Now add it to your Lambda function:
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs22.x
Layers:
- !Ref UtilsLayer
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: false
EntryPoints:
- index.ts
External:
- utils
- "@aws-sdk/*"
Step 4: Use Layer in Lambda Code
In your index.js
or index.ts
:
import { greet } from 'utils';
export const handler = async () => {
return {
statusCode: 200,
body: JSON.stringify({ message: greet("SAM Developer") })
};
};
BONUS: Using Powertools Logger as a Global Layer
If you want structured logging, tracing, and metrics β use AWS Lambda Powertools for TypeScript as a global layer. AWS provides it as a public layer:
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Layers:
- !Sub
arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:24
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: false
EntryPoints:
- index.ts
External:
- "@aws-lambda-powertools/*"
- "@aws-sdk/*"
or globally:
Globals:
Function:
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:24
Example Use
import { Logger } from "@aws-lambda-powertools/logger";
const logger = new Logger({ serviceName: "MyApp" });
export const handler = async () => {
logger.info("Lambda invoked");
return {
statusCode: 200,
body: JSON.stringify({ message: "Logged with Powertools" })
};
};
Conclusion
You now know how to:
-
Create a reusable Lambda Layer with esbuild
-
Structure a Makefile build process for SAM
-
Use AWS Lambda Powertools for structured logging
Previous Posts in the Series
1 β Mastering Serverless with AWS SAM
2 β Optimizing AWS SAM Node.js Lambda with esbuild
3 β Managing Environment Variables and Secrets in AWS Lambda (Node.js + SAM)