Lambda Layers: Shared Dependencies Without Bloated Deployment Packages

2 min readCloud Infrastructure

Lambda layers let multiple functions share libraries, runtimes, and configuration without bundling duplicates into each deployment package. Understanding layer mounting, version pinning, and the 250 MB limit saves debugging time when layers behave unexpectedly.

awslambdaserverless

What Lambda layers solve

A Lambda function's deployment package contains your code and its dependencies. Without layers, each function bundles its own copy of shared libraries — pandas, boto3, numpy, cryptography — even when ten functions use the same version.

Layers extract that shared content into a separate artifact that multiple functions reference. The layer is uploaded once and reused across functions, accounts, and regions (if shared).

Without layers:
  function-a.zip (50 MB): my_code.py + pandas (15 MB) + numpy (20 MB) + boto3 (10 MB)
  function-b.zip (48 MB): my_code.py + pandas (15 MB) + numpy (20 MB) + boto3 (10 MB)
  → 98 MB total deployed

With a shared layer:
  data-science-layer.zip (45 MB): pandas + numpy + boto3
  function-a.zip (5 MB): my_code.py
  function-b.zip (3 MB): my_code.py
  → 53 MB total deployed, faster uploads

How layers are mounted at runtime

ConceptAWS Lambda

Lambda mounts layers at /opt. Your code finds layer contents in /opt/python (Python), /opt/nodejs/node_modules (Node.js), /opt/lib (native libraries), etc. The Lambda runtime adds these paths to the language's module search path automatically.

Prerequisites

  • Lambda function basics
  • Python/Node.js module resolution
  • zip file structure

Key Points

  • Layers are extracted to /opt at function invocation. Your imports work without any special code.
  • Multiple layers are mounted in the order listed — later layers can override earlier ones.
  • A function can use up to 5 layers. Total unzipped size (function + all layers) must be under 250 MB.
  • Layer versions are immutable. Attaching layer:version-3 always gives you that exact version.

Layer package structure

The directory structure inside the layer zip determines where Lambda extracts the contents. For Python:

# Layer zip for Python packages:
python/
  lib/
    python3.11/
      site-packages/
        pandas/
        numpy/

# OR simply:
python/
  my_package.py
  my_module/
    __init__.py

Lambda adds /opt/python and /opt/python/lib/python3.x/site-packages to sys.path. Packages in these directories are importable.

For a custom runtime or native binaries:

# Layer zip for native libraries:
lib/
  libssl.so.1.1
  libcrypto.so.1.1

bin/
  my-binary

Lambda adds /opt/lib to LD_LIBRARY_PATH and /opt/bin to PATH.

Creating and attaching a layer

# Build the layer
pip install pandas numpy --target ./python/lib/python3.11/site-packages
zip -r data-science-layer.zip python/

# Publish to Lambda
aws lambda publish-layer-version \
  --layer-name data-science-layer \
  --zip-file fileb://data-science-layer.zip \
  --compatible-runtimes python3.11 python3.12

# Output includes the layer ARN:
# arn:aws:lambda:us-east-1:123456789012:layer:data-science-layer:1
# Attach in Terraform
resource "aws_lambda_function" "analysis" {
  function_name = "data-analysis"
  runtime       = "python3.11"
  handler       = "handler.main"
  layers = [
    "arn:aws:lambda:us-east-1:123456789012:layer:data-science-layer:1"
  ]
  # ...
}

The layer ARN includes the version number. Changing the version number in the ARN updates which layer version the function uses — you must redeploy the function to pick up a new layer version.

Version pinning and the update problem

Layers are versioned. data-science-layer:1 is immutable — publishing an updated version creates data-science-layer:2. Functions referencing :1 are unaffected until you update their layer ARN.

This is an advantage for stability but creates a maintenance burden: updating a shared library means publishing a new layer version and updating every function that uses it. For large organizations with many Lambda functions, this can be automated through CI/CD.

💡AWS-managed layers vs custom layers

AWS provides managed layers for some common dependencies:

  • AWS SDK (boto3 for Python): included in all Lambda runtimes, no layer needed.
  • AWS Lambda Powertools: arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:latest

AWS-managed layers are updated by AWS. Using latest instead of a specific version number means you automatically pick up updates — useful for security patches, risky for breaking changes. For production, pin to a specific layer version.

Third-party layers (Datadog, New Relic APM agents) are often distributed as public layers. The provider publishes the ARN; you attach it to your function. These follow the same version pinning rules.

A Lambda function uses a custom layer containing pandas. After attaching a new layer version (version 2 with an updated pandas), the function still uses the old pandas version during test invocations. What is the most likely cause?

easy

The layer ARN in the function configuration was updated from :1 to :2. The function was not redeployed.

  • ALambda caches layer content across versions — the cache must be invalidated manually
    Incorrect.Lambda does not cache layer content independently from function deployments. Each cold start mounts the layers specified in the current function configuration.
  • BThe function configuration was updated but the function was not deployed — changes to layer ARNs require a function deployment to take effect
    Correct!Updating the layer ARN in the function configuration is not sufficient. The change must be deployed (a new function version created). Until deployment, the function continues using the configuration of its last deployed version. In the AWS console, updating and saving configuration triggers a deployment automatically. In Terraform or CDK, apply the change to create a new function version.
  • CLayer version 2 is incompatible with the function's Python runtime
    Incorrect.The question states the layer was published with compatible-runtimes including the function's Python version. Incompatibility would cause an import error, not silently serve the old version.
  • DThe layer order matters — pandas in layer 2 is being overridden by layer 1
    Incorrect.The function has one layer, not two. Layer ordering is not relevant here.

Hint:Think about when Lambda picks up configuration changes. Does saving a configuration update immediately affect running invocations?