DEV Community

Cover image for Creating and Using Lambda Layers with AWS SAM and Node.js
Márcio Coelho
Márcio Coelho

Posted on • Edited on

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
Enter fullscreen mode Exit fullscreen mode

Your utils.js could be something like:

export const greet = (name: string) => {
  return `Hello, ${name}!`;
};
Enter fullscreen mode Exit fullscreen mode

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"]
}
Enter fullscreen mode Exit fullscreen mode

Create a Makefile inside the utils/ folder:

build-Utils:
        ./node_modules/.bin/esbuild utils.ts --bundle --platform=node --target=node22 --outfile=$(ARTIFACTS_DIR)/nodejs/index.js
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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/*"
Enter fullscreen mode Exit fullscreen mode

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") })
  };
};
Enter fullscreen mode Exit fullscreen mode

🌟 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/*"
Enter fullscreen mode Exit fullscreen mode

or globally:

Globals:
  Function:
    Layers:
      - !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:24
Enter fullscreen mode Exit fullscreen mode

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" })
  };
};

Enter fullscreen mode Exit fullscreen mode

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


Top comments (0)

OSZAR »