Skip to main content

Lambda layers

Layers are attached to generated functions through LambdaApiConfig and @layer. Use LambdaApi as the entry point.

Common and named layers​

Pass existing CDK layer objects in layers or add them with add_common_layer. They are attached to every generated function:

from aws_cdk import aws_lambda as lambda_
from lambda_api_decorators import GET, layer
from lambda_api_decorators_cdk import LambdaApi, LambdaApiConfig

config = LambdaApiConfig(layers=[shared_layer])
config.register_layer("database", database_layer)

@GET("/orders")
@layer("database")
def orders(event, context):
return {"statusCode": 200, "body": "ok"}

api = LambdaApi(self, "Api", lambda_path="lambdas", config=config)

shared_layer is common to all functions; database_layer is added only to orders. The resulting order is common layers first, followed by the selected named layers. Common layer objects are de-duplicated when added through the config mutator. A named layer must be an ILayerVersion object.

Autodiscovery with layers_path​

layers_path is a LambdaApi constructor argument. It is not a LambdaApiConfig argument:

api = LambdaApi(
self,
"Api",
lambda_path="lambdas",
layers_path="layers",
config=LambdaApiConfig(default_runtime="python3.14"),
)

Each eligible direct child directory of layers_path is a candidate named by its directory name. A candidate is constructed only when a handler uses that exact name with @layer("name"). Hidden entries and __pycache__ are ignored; files and file symlinks are not candidates, while directory symlinks are. Nested directories remain part of the parent layer rather than becoming names of their own.

The expected layout is:

project/
├── lambdas/
│ ├── orders.py
│ └── requirements.txt # normal function dependencies
├── layers/
│ └── database/
│ ├── requirements.txt
│ └── python/ # optional layer source/package tree
└── stack.py

The directory itself is passed as the entry to CDK's PythonLayerVersion. Put Python dependencies for that layer in its layers/database/requirements.txt, following the CDK Python layer packaging contract. Dependencies shared by normal functions belong in lambdas/requirements.txt (or the corresponding packaging root selected by SourceLayout); that file is not a Lambda layer.

Autodiscovered layers require an effective Python runtime. The builder derives their compatible runtimes from the handlers that request them. If no concrete runtime exists, or the effective runtime is not Python, construction raises ValueError.

Verified failure behavior​

The current implementation and tests establish these cases:

  • a missing layers_path, or a path that is not a directory, raises ValueError;
  • an unknown @layer name raises KeyError;
  • an explicit register_layer entry wins over an autodiscovered directory of the same name, and that directory is not constructed;
  • incompatible explicit/common layers raise ValueError when their exposed compatibility metadata does not include the effective runtime;
  • unreadable or unusable layer compatibility metadata raises ValueError.

Repeated layer declarations are retained as repeated selections. The builder also de-duplicates runtime names when calculating the compatibility list for an autodiscovered layer. No broader duplicate-directory behavior is documented because the checked code does not define a separate duplicate-directory case.

For lower-level builds, ResourceBuilder.build and build_http expose the same layers_path behavior; ResourceBuilder is an advanced alternative, not the recommended starting point.