Create AWS Lambda Layer Versions

The aws:lambda/layerVersion:LayerVersion resource, part of the Pulumi AWS provider, publishes a versioned Lambda Layer that packages shared code and dependencies for reuse across multiple Lambda functions. This guide focuses on three capabilities: local and S3-based deployment, runtime and architecture compatibility, and change detection.

Layers are standalone resources that functions reference by ARN. S3-based layers require existing S3 objects containing the layer ZIP. The examples are intentionally small. Combine them with your own Lambda functions and layer permission policies.

Deploy a layer from a local ZIP file

Most deployments package shared code into a ZIP and specify which runtimes can use it.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.lambda.LayerVersion("example", {
    code: new pulumi.asset.FileArchive("lambda_layer_payload.zip"),
    layerName: "lambda_layer_name",
    compatibleRuntimes: ["nodejs20.x"],
});
import pulumi
import pulumi_aws as aws

example = aws.lambda_.LayerVersion("example",
    code=pulumi.FileArchive("lambda_layer_payload.zip"),
    layer_name="lambda_layer_name",
    compatible_runtimes=["nodejs20.x"])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := lambda.NewLayerVersion(ctx, "example", &lambda.LayerVersionArgs{
			Code:      pulumi.NewFileArchive("lambda_layer_payload.zip"),
			LayerName: pulumi.String("lambda_layer_name"),
			CompatibleRuntimes: pulumi.StringArray{
				pulumi.String("nodejs20.x"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Lambda.LayerVersion("example", new()
    {
        Code = new FileArchive("lambda_layer_payload.zip"),
        LayerName = "lambda_layer_name",
        CompatibleRuntimes = new[]
        {
            "nodejs20.x",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.LayerVersion;
import com.pulumi.aws.lambda.LayerVersionArgs;
import com.pulumi.asset.FileArchive;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LayerVersion("example", LayerVersionArgs.builder()
            .code(new FileArchive("lambda_layer_payload.zip"))
            .layerName("lambda_layer_name")
            .compatibleRuntimes("nodejs20.x")
            .build());

    }
}
resources:
  example:
    type: aws:lambda:LayerVersion
    properties:
      code:
        fn::FileArchive: lambda_layer_payload.zip
      layerName: lambda_layer_name
      compatibleRuntimes:
        - nodejs20.x

The code property points to your local ZIP file. The compatibleRuntimes property lists which Lambda runtimes can attach this layer; functions using other runtimes cannot reference it. Each deployment creates a new immutable layer version.

Deploy a layer from S3 with multiple runtimes

For larger packages or CI/CD workflows, S3 provides better upload performance and integrates with existing artifact storage.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.lambda.LayerVersion("example", {
    s3Bucket: lambdaLayerZip.bucket,
    s3Key: lambdaLayerZip.key,
    layerName: "lambda_layer_name",
    compatibleRuntimes: [
        "nodejs20.x",
        "python3.12",
    ],
    compatibleArchitectures: [
        "x86_64",
        "arm64",
    ],
});
import pulumi
import pulumi_aws as aws

example = aws.lambda_.LayerVersion("example",
    s3_bucket=lambda_layer_zip["bucket"],
    s3_key=lambda_layer_zip["key"],
    layer_name="lambda_layer_name",
    compatible_runtimes=[
        "nodejs20.x",
        "python3.12",
    ],
    compatible_architectures=[
        "x86_64",
        "arm64",
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := lambda.NewLayerVersion(ctx, "example", &lambda.LayerVersionArgs{
			S3Bucket:  pulumi.Any(lambdaLayerZip.Bucket),
			S3Key:     pulumi.Any(lambdaLayerZip.Key),
			LayerName: pulumi.String("lambda_layer_name"),
			CompatibleRuntimes: pulumi.StringArray{
				pulumi.String("nodejs20.x"),
				pulumi.String("python3.12"),
			},
			CompatibleArchitectures: pulumi.StringArray{
				pulumi.String("x86_64"),
				pulumi.String("arm64"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Lambda.LayerVersion("example", new()
    {
        S3Bucket = lambdaLayerZip.Bucket,
        S3Key = lambdaLayerZip.Key,
        LayerName = "lambda_layer_name",
        CompatibleRuntimes = new[]
        {
            "nodejs20.x",
            "python3.12",
        },
        CompatibleArchitectures = new[]
        {
            "x86_64",
            "arm64",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.LayerVersion;
import com.pulumi.aws.lambda.LayerVersionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LayerVersion("example", LayerVersionArgs.builder()
            .s3Bucket(lambdaLayerZip.bucket())
            .s3Key(lambdaLayerZip.key())
            .layerName("lambda_layer_name")
            .compatibleRuntimes(            
                "nodejs20.x",
                "python3.12")
            .compatibleArchitectures(            
                "x86_64",
                "arm64")
            .build());

    }
}
resources:
  example:
    type: aws:lambda:LayerVersion
    properties:
      s3Bucket: ${lambdaLayerZip.bucket}
      s3Key: ${lambdaLayerZip.key}
      layerName: lambda_layer_name
      compatibleRuntimes:
        - nodejs20.x
        - python3.12
      compatibleArchitectures:
        - x86_64
        - arm64

The s3Bucket and s3Key properties reference an existing S3 object containing your layer ZIP. The compatibleRuntimes property supports multiple runtime families (Node.js and Python here), while compatibleArchitectures declares support for both x86_64 and arm64 Lambda functions.

Add metadata and change detection to layers

Production layers benefit from descriptive metadata and automatic redeployment when code changes.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const example = new aws.lambda.LayerVersion("example", {
    code: new pulumi.asset.FileArchive("lambda_layer_payload.zip"),
    layerName: "multi_runtime_layer",
    description: "Shared utilities for Lambda functions",
    licenseInfo: "MIT",
    sourceCodeHash: std.filebase64sha256({
        input: "lambda_layer_payload.zip",
    }).then(invoke => invoke.result),
    compatibleRuntimes: [
        "nodejs18.x",
        "nodejs20.x",
        "python3.11",
        "python3.12",
    ],
    compatibleArchitectures: [
        "x86_64",
        "arm64",
    ],
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std

example = aws.lambda_.LayerVersion("example",
    code=pulumi.FileArchive("lambda_layer_payload.zip"),
    layer_name="multi_runtime_layer",
    description="Shared utilities for Lambda functions",
    license_info="MIT",
    source_code_hash=std.filebase64sha256(input="lambda_layer_payload.zip").result,
    compatible_runtimes=[
        "nodejs18.x",
        "nodejs20.x",
        "python3.11",
        "python3.12",
    ],
    compatible_architectures=[
        "x86_64",
        "arm64",
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		invokeFilebase64sha256, err := std.Filebase64sha256(ctx, &std.Filebase64sha256Args{
			Input: "lambda_layer_payload.zip",
		}, nil)
		if err != nil {
			return err
		}
		_, err = lambda.NewLayerVersion(ctx, "example", &lambda.LayerVersionArgs{
			Code:           pulumi.NewFileArchive("lambda_layer_payload.zip"),
			LayerName:      pulumi.String("multi_runtime_layer"),
			Description:    pulumi.String("Shared utilities for Lambda functions"),
			LicenseInfo:    pulumi.String("MIT"),
			SourceCodeHash: pulumi.String(invokeFilebase64sha256.Result),
			CompatibleRuntimes: pulumi.StringArray{
				pulumi.String("nodejs18.x"),
				pulumi.String("nodejs20.x"),
				pulumi.String("python3.11"),
				pulumi.String("python3.12"),
			},
			CompatibleArchitectures: pulumi.StringArray{
				pulumi.String("x86_64"),
				pulumi.String("arm64"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Lambda.LayerVersion("example", new()
    {
        Code = new FileArchive("lambda_layer_payload.zip"),
        LayerName = "multi_runtime_layer",
        Description = "Shared utilities for Lambda functions",
        LicenseInfo = "MIT",
        SourceCodeHash = Std.Filebase64sha256.Invoke(new()
        {
            Input = "lambda_layer_payload.zip",
        }).Apply(invoke => invoke.Result),
        CompatibleRuntimes = new[]
        {
            "nodejs18.x",
            "nodejs20.x",
            "python3.11",
            "python3.12",
        },
        CompatibleArchitectures = new[]
        {
            "x86_64",
            "arm64",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.LayerVersion;
import com.pulumi.aws.lambda.LayerVersionArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Filebase64sha256Args;
import com.pulumi.asset.FileArchive;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LayerVersion("example", LayerVersionArgs.builder()
            .code(new FileArchive("lambda_layer_payload.zip"))
            .layerName("multi_runtime_layer")
            .description("Shared utilities for Lambda functions")
            .licenseInfo("MIT")
            .sourceCodeHash(StdFunctions.filebase64sha256(Filebase64sha256Args.builder()
                .input("lambda_layer_payload.zip")
                .build()).result())
            .compatibleRuntimes(            
                "nodejs18.x",
                "nodejs20.x",
                "python3.11",
                "python3.12")
            .compatibleArchitectures(            
                "x86_64",
                "arm64")
            .build());

    }
}
resources:
  example:
    type: aws:lambda:LayerVersion
    properties:
      code:
        fn::FileArchive: lambda_layer_payload.zip
      layerName: multi_runtime_layer
      description: Shared utilities for Lambda functions
      licenseInfo: MIT
      sourceCodeHash:
        fn::invoke:
          function: std:filebase64sha256
          arguments:
            input: lambda_layer_payload.zip
          return: result
      compatibleRuntimes:
        - nodejs18.x
        - nodejs20.x
        - python3.11
        - python3.12
      compatibleArchitectures:
        - x86_64
        - arm64

The description and licenseInfo properties document what the layer contains and its licensing terms. The sourceCodeHash property triggers layer version creation when the ZIP file changes; use filebase64sha256 to compute the hash from your local file. This ensures functions always get the latest code without manual version management.

Beyond these examples

These snippets focus on specific layer-level features: local and S3-based deployment, runtime and architecture compatibility, and metadata and change detection. They’re intentionally minimal rather than full sharing solutions.

The examples may reference pre-existing infrastructure such as S3 buckets with layer ZIP files for S3-based deployment. They focus on publishing the layer rather than provisioning storage or configuring function access.

To keep things focused, common layer patterns are omitted, including:

  • Version retention (skipDestroy property)
  • Layer permissions for cross-account access
  • Integration with Lambda functions (layers property on Function resource)

These omissions are intentional: the goal is to illustrate how each layer feature is wired, not provide drop-in sharing modules. See the Lambda LayerVersion resource reference for all available configuration options.

Let's create AWS Lambda Layer Versions

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Deployment & Code Management
How do I deploy a Lambda layer?

You have two options:

  1. Local file - Use code with FileArchive: code: new pulumi.asset.FileArchive("file.zip")
  2. S3 bucket - Use s3Bucket, s3Key, and optionally s3ObjectVersion

These options conflict; you cannot use both simultaneously.

When should I use S3 instead of local files for deployment?
For larger deployment packages, S3 is recommended because the S3 API has better support for uploading large files efficiently.
How do I trigger layer updates when my code changes?
Set sourceCodeHash to a base64-encoded SHA256 hash of your package file using filebase64sha256("file.zip") or base64sha256(file("file.zip")). When the hash changes, Pulumi creates a new layer version.
Can I use an S3 bucket in a different region than my layer?
No, the S3 bucket must reside in the same AWS region where you’re creating the Lambda layer.
Versioning & Lifecycle
What does skipDestroy do and what are the cost implications?
When skipDestroy is true, Pulumi won’t destroy layer versions even during pulumi destroy. These become intentional dangling resources that remain in your AWS account and may incur extra storage expense. The default is false.
What happens when I update layer properties?
When skipDestroy is false (default), changing properties like compatibleRuntimes, description, layerName, licenseInfo, sourceCodeHash, or deployment source forces deletion of the existing layer version and creation of a new one.
What's the difference between layerArn and arn?
layerArn is the ARN without version (e.g., arn:aws:lambda:region:account:layer:name), while arn includes the version number (e.g., arn:aws:lambda:region:account:layer:name:1).
Compatibility & Configuration
How many runtimes can I specify for a layer?
You can specify up to 15 runtimes in the compatibleRuntimes list.
What architectures are supported for Lambda layers?
Lambda layers support x86_64 and arm64 architectures, specified via the compatibleArchitectures property.
Common Issues
Why can't I use both code and s3Bucket?
The code property conflicts with the S3-prefixed options (s3Bucket, s3Key, s3ObjectVersion). You must choose either local file deployment or S3 deployment, not both.
What deployment package structure does my layer need?
The required structure varies depending on which compatibleRuntimes you specify. Each runtime has specific directory structure requirements for layer contents.

Using a different cloud?

Explore serverless guides for other cloud providers: