Skip to content
AWS aws serverless 5 min read

Lambda Layers

When you build several AWS Lambda functions, you often copy the same libraries into each one. A Lambda layer is a ZIP archive of shared code or dependencies that Lambda mounts into your function at runtime, so you only package it once. AWS Lambda is the service that runs your code without you managing servers. Layers keep your deployment packages small, speed up uploads, and let you update a shared library in one place instead of in every function.

What a layer actually is

A layer is just a ZIP file containing libraries (for example, your Python requests package or a Node.js SDK), a custom runtime, or other supporting files. When a function uses a layer, Lambda extracts the layer’s contents into the /opt directory inside the execution environment. Your function code stays in its own package, and the layer content appears alongside it under /opt.

The folder structure inside the ZIP matters, because each runtime looks in a specific path under /opt:

RuntimePut files in ZIP underLambda finds them at
Node.jsnodejs/node_modules//opt/nodejs/node_modules
Pythonpython/ or python/lib/python3.13/site-packages/on the PYTHONPATH
Javajava/lib/on the classpath
Any (binaries)bin/on PATH (/opt/bin)

Gotcha: if you ZIP your node_modules at the top level instead of under nodejs/, the layer attaches fine but your require() calls fail at runtime. The folder prefix is what makes the runtime see the files.

When to use a layer (and when not to)

Use a layer when:

  • Multiple functions share the same dependencies (an internal utility package, an SDK).
  • You want to update a shared library once without redeploying every function’s code.
  • Your dependencies are large and slow your code uploads down.

Do not use a layer when:

  • You have one function with a unique dependency set — just package it with the code.
  • Your dependency tree is complex or huge. Juggling several layers gets fragile, and you hit limits (below). For heavy native dependencies (machine learning libraries, image processing tools), a container image (a packaged filesystem you deploy as the function) is usually simpler.

The size limit you must know

A function and all its attached layers share a single 250 MB unzipped limit. This is the most common surprise. If your function code is 100 MB unzipped and you attach two layers that add 200 MB unzipped, the deployment fails — layers do not get their own separate budget.

A single function can attach up to 5 layers. If 250 MB unzipped is not enough, switch to a container image, which allows up to 10 GB.

Creating a layer

You build the layer ZIP locally, publish it, then attach it to a function. Below is a Python example.

# Build the layer content in the required folder structure
mkdir -p python
pip install requests==2.32.3 -t python/
zip -r requests-layer.zip python/

# Publish the layer (this creates version 1)
aws lambda publish-layer-version \
  --layer-name shared-requests \
  --description "requests 2.32.3 for Python" \
  --zip-file fileb://requests-layer.zip \
  --compatible-runtimes python3.13

Output:

{
    "LayerArn": "arn:aws:lambda:us-east-1:111122223333:layer:shared-requests",
    "LayerVersionArn": "arn:aws:lambda:us-east-1:111122223333:layer:shared-requests:1",
    "Version": 1,
    "CompatibleRuntimes": ["python3.13"]
}

Note the :1 at the end of the LayerVersionArn. Layers are versioned, and every publish creates a new immutable version. There is no “update in place” — you publish version 2, then re-point functions at it. This versioning is manual; nothing auto-updates your functions.

Console steps to create a layer

  1. Open the Lambda console and choose Layers in the left menu.
  2. Click Create layer.
  3. Enter a name (for example, shared-requests) and an optional description.
  4. Upload your ZIP file (or point to an Amazon S3 object if it is larger than 50 MB).
  5. Choose compatible runtimes (for example, python3.13) and architecture.
  6. Click Create. The new version number appears on the layer detail page.

Attaching a layer to a function

You attach a layer by its version ARN (Amazon Resource Name — the unique ID of the layer version).

aws lambda update-function-configuration \
  --function-name order-processor \
  --layers arn:aws:lambda:us-east-1:111122223333:layer:shared-requests:1

Output:

{
    "FunctionName": "order-processor",
    "Runtime": "python3.13",
    "Layers": [
        {
            "Arn": "arn:aws:lambda:us-east-1:111122223333:layer:shared-requests:1",
            "CodeSize": 1048576
        }
    ]
}

Warning: --layers replaces the entire list. If your function already has layers, include all the ARNs you want to keep, or you will silently detach the others.

Console steps to attach a layer

  1. Open your function in the Lambda console.
  2. Scroll to the Layers panel at the bottom of the Code tab and click Add a layer.
  3. Choose Custom layers, pick shared-requests, and select the version.
  4. Click Add.

Infrastructure as Code

Defining the layer and the wiring in code keeps it repeatable. Here is an AWS SAM / CloudFormation snippet.

Resources:
  SharedRequestsLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: shared-requests
      ContentUri: ./layer/
      CompatibleRuntimes:
        - python3.13

  OrderProcessor:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.handler
      Runtime: python3.13
      CodeUri: ./src/
      Layers:
        - !Ref SharedRequestsLayer

Cost note

Layers themselves have no extra charge. You pay for the S3 storage of the layer ZIP (cents per month) and the usual Lambda compute. The real saving is operational: smaller code packages upload faster and one update propagates to many functions. Note that a large layer adds to your unzipped size, which can slightly affect cold-start time on some runtimes.

Best practices

  • Always build the layer with the exact folder prefix the runtime expects (nodejs/, python/, java/lib/).
  • Pin dependency versions in the layer so functions get reproducible builds.
  • Treat layer versions as immutable releases; bump the version and roll functions forward deliberately.
  • Keep layers small and focused (one concern per layer) rather than one giant catch-all layer.
  • Watch the combined 250 MB unzipped budget; if you are fighting it, move to a container image.
  • Share layers across accounts with a resource policy only when you truly need to, and grant least privilege.
Last updated June 15, 2026
Was this helpful?