From 1cbc261c7841be7fc6fd2e734b04a8862c9be488 Mon Sep 17 00:00:00 2001 From: svozza Date: Tue, 28 Jul 2026 20:53:39 +0100 Subject: [PATCH 1/3] fix(layers): do not ship AWS SDK clients in the Lambda layer The layer is mounted at /opt/nodejs/node_modules, which precedes /var/runtime/node_modules on NODE_PATH. Any SDK package shipped in the layer therefore shadows the runtime's copy for customer code as well, not just for Powertools. Because the layer only ever included a subset of the SDK - notably @aws-sdk/client-dynamodb but never @aws-sdk/lib-dynamodb - functions using the DynamoDB DocumentClient resolved a layer-provided client against a runtime-provided lib. When those straddle the AWS SDK 3.928.0 boundary, which moved serializerMiddleware registration from per-command to per-client, the mismatch fails at runtime with: serializerMiddleware is not found when adding DocumentMarshall middleware before serializerMiddleware The Node.js Lambda runtime already provides a complete, self-consistent AWS SDK v3, so rely on that instead of exposing a partial one. zod and @smithy/* are not provided by the runtime and remain in the layer. Closes #5511 --- layers/src/layer-publisher-stack.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/layers/src/layer-publisher-stack.ts b/layers/src/layer-publisher-stack.ts index 054f66214c..7ed00b9227 100644 --- a/layers/src/layer-publisher-stack.ts +++ b/layers/src/layer-publisher-stack.ts @@ -107,15 +107,19 @@ export class LayerPublisherStack extends Stack { 'node_modules/@aws-sdk/**/README.md ', ]; const buildCommands: string[] = []; - // We install these to get the latest version of the packages - const modulesToInstall: string[] = [ - '@aws-sdk/client-dynamodb', - '@aws-sdk/util-dynamodb', - '@aws-sdk/client-ssm', - '@aws-sdk/client-secrets-manager', - '@aws-sdk/client-appconfigdata', - 'zod', - ]; + // We deliberately do NOT ship any @aws-sdk/* client in the layer. + // + // The layer is mounted at /opt/nodejs/node_modules, which precedes + // /var/runtime/node_modules on NODE_PATH. Any SDK package we ship + // therefore shadows the runtime's copy for customer code too. Since + // we only ever shipped a subset (e.g. client-dynamodb but never + // lib-dynamodb), customers using the DocumentClient ended up with a + // layer-provided client and a runtime-provided lib, and any breaking + // change across that boundary surfaces as a runtime error. + // + // The Node.js runtime already provides a complete, self-consistent + // AWS SDK v3, so we rely on it instead of exposing a partial one. + const modulesToInstall: string[] = ['zod']; if (buildFromLocal) { for (const util of utilities) { From cd65aa3535839a3b3b0a3a432223bf3b6da81736 Mon Sep 17 00:00:00 2001 From: svozza Date: Tue, 28 Jul 2026 20:55:26 +0100 Subject: [PATCH 2/3] docs(layers): stop telling customers to exclude @aws-sdk/* from bundles The layer no longer ships AWS SDK clients, so the previous wording - that both @aws-lambda-powertools/* and @aws-sdk/* are 'already present the layer' - is no longer accurate. Remove @aws-sdk/* from the esbuild exclusion notes and from the CDK, SAM and Serverless Framework snippets, so customers bundle their own SDK rather than relying on whatever the layer happens to expose. Bundling your own SDK resolves it from /var/task, which takes precedence over both the layer and the runtime and is therefore the only configuration guaranteed to be self-consistent. Also fixes the missing 'in' in 'present the layer'. --- docs/getting-started/lambda-layers.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/getting-started/lambda-layers.md b/docs/getting-started/lambda-layers.md index 4ba544475a..5ac2da8506 100644 --- a/docs/getting-started/lambda-layers.md +++ b/docs/getting-started/lambda-layers.md @@ -154,7 +154,7 @@ Change `{aws::region}` to your AWS region, e.g. `eu-west-1`, and run the followi } ``` - If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` and `@aws-sdk/*` from being bundled since the packages are already present the layer: + If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` from being bundled since the packages are already present in the layer: ```typescript new NodejsFunction(this, 'Function', { @@ -162,7 +162,6 @@ Change `{aws::region}` to your AWS region, e.g. `eu-west-1`, and run the followi bundling: { externalModules: [ '@aws-lambda-powertools/*', - '@aws-sdk/*', ], } }); @@ -223,7 +222,7 @@ Change `{aws::region}` to your AWS region, e.g. `eu-west-1`, and run the followi - {{resolve:ssm:/aws/service/powertools/typescript/generic/all/latest}} ``` - If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` and `@aws-sdk/*` from being bundled since the packages are already present the layer: + If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` from being bundled since the packages are already present in the layer: ```yaml hl_lines="5-14" MyLambdaFunction: @@ -237,7 +236,6 @@ Change `{aws::region}` to your AWS region, e.g. `eu-west-1`, and run the followi Minify: true External: - '@aws-lambda-powertools/*' - - '@aws-sdk/*' ``` Check the [documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build-typescript.html) for more details. @@ -252,14 +250,13 @@ Change `{aws::region}` to your AWS region, e.g. `eu-west-1`, and run the followi - arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:49 ``` - If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` and `@aws-sdk/*` from being bundled since the packages are already present the layer: + If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools/*` from being bundled since the packages are already present in the layer: ```yaml custom: esbuild: external: - '@aws-lambda-powertools/*' - - '@aws-sdk/*' ``` Check the [documentation](https://floydspace.github.io/serverless-esbuild/) for more details. From f17cefb8a1a8fe0dd38496d9dfe723bcb5f0fd39 Mon Sep 17 00:00:00 2001 From: svozza Date: Tue, 28 Jul 2026 21:09:10 +0100 Subject: [PATCH 3/3] docs(layers): note that the layer no longer bundles the AWS SDK Record that layer version 49 is the last to bundle AWS SDK v3 clients, explain that /opt/nodejs/node_modules took precedence so those clients were used by customer code too, and that only a subset ever shipped - which is what allowed mismatched SDK packages at runtime. --- docs/getting-started/lambda-layers.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/getting-started/lambda-layers.md b/docs/getting-started/lambda-layers.md index 5ac2da8506..3ff440555c 100644 --- a/docs/getting-started/lambda-layers.md +++ b/docs/getting-started/lambda-layers.md @@ -361,3 +361,16 @@ npm i -D @aws-lambda-powertools/logger - **Version synchronization**: Keep your local development dependencies in sync with the Lambda Layer version to maintain consistency Following these practices prevents version conflicts that can cause unexpected behavior, such as failed `instanceof` checks or inconsistent behavior between your local development environment and the Lambda execution environment. + +???+ note "AWS SDK v3 is no longer included in the layer" + + Layer version `49` is the last one to bundle AWS SDK v3 clients; later + versions do not include any `@aws-sdk/*` package. + + The layer is mounted at `/opt/nodejs/node_modules`, which takes precedence + over the runtime's own copy, so the bundled clients were picked up by your + function code as well. Since the layer only ever included a subset of the + SDK, this could leave you with mismatched SDK packages at runtime. + + Install the clients your code needs as regular dependencies and bundle them + with your function, or rely on the copy the Lambda Node.js runtime provides.