AWS Security ChangesHomeSearch

AWS lambda documentation change

Service: lambda · 2025-11-22 · Documentation low

File: lambda/latest/dg/typescript-handler.md

Summary

Added documentation sections for CommonJS/ES Modules, Node.js initialization patterns, and updated handler signatures. Emphasized using top-level await for initialization to complete async tasks (like AWS service calls) during cold starts to prevent runtime errors. Deprecated callback-based handlers for Node.js 24+.

Security assessment

The changes focus on best practices for module systems, initialization timing, and handler patterns. While the Node.js initialization section warns about potential AWS service call failures due to time-sensitive signatures if async tasks are not completed during initialization, this is framed as a reliability/error prevention concern rather than a direct security vulnerability. No explicit security vulnerabilities, exploits, or security feature enhancements are mentioned.

Diff

diff --git a/lambda/latest/dg/typescript-handler.md b/lambda/latest/dg/typescript-handler.md
index 9a4abc806..e715f6146 100644
--- a//lambda/latest/dg/typescript-handler.md
+++ b//lambda/latest/dg/typescript-handler.md
@@ -5 +5 @@
-Set up your projectExample functionHandler naming conventionsInput event objectValid handler patternsUsing the SDK for JavaScriptAccessing environment variablesUsing global stateBest practices
+Set up your projectExample functionCommonJS and ES ModulesNode.js initializationHandler naming conventionsInput event objectValid handler patternsUsing the SDK for JavaScriptAccessing environment variablesUsing global stateBest practices
@@ -18,0 +19,4 @@ This page describes how to work with Lambda function handlers in TypeScript, inc
+  * CommonJS and ES Modules
+
+  * Node.js initialization
+
@@ -67 +71 @@ The following example Lambda function code takes in information about an order,
-This example uses an ES module handler. Lambda supports both ES module and CommonJS handlers. For more information, see [Designating a function handler as an ES module](./lambda-nodejs.html#designate-es-module).
+This example uses an ES module handler. Lambda supports both ES module and CommonJS handlers. For more information, see [CommonJS and ES Modules](./nodejs-handler.html#nodejs-commonjs-es-modules).
@@ -143,0 +148,14 @@ For this function to work properly, its [ execution role](./lambda-intro-executi
+## CommonJS and ES Modules
+
+Node.js supports two module systems: CommonJS and ECMAScript modules (ES modules). Lambda recommends using ES modules as it supports top-level await, which enables asynchronous tasks to be completed during execution environment initialization.
+
+Node.js treats files with a `.cjs` file name extension as CommonJS modules while a `.mjs` extension denotes ES modules. By default, Node.js treats files with the `.js` file name extension as CommonJS modules. You can configure Node.js to treat `.js` files as ES modules by specifying the `type` as `module` in the function's `package.json` file. You can configure Node.js in Lambda to detect automatically whether a `.js` file should be treated as CommonJS or as an ES module by adding the `—experimental-detect-module` flag to the `NODE_OPTIONS` environment variable. For more information, see [Experimental Node.js features](./lambda-nodejs.html#nodejs-experimental-features).
+
+The following examples show function handlers written using both ES modules and CommonJS modules. The remaining examples on this page all use ES modules.
+
+## Node.js initialization
+
+Node.js uses a non-blocking I/O model that supports efficient asynchronous operations using an event loop. For example, if Node.js makes a network call, the function continues to process other operations without blocking on a network response. When the network response is received, it is placed into the callback queue. Tasks from the queue are processed when the current task completes.
+
+Lambda recommends using top-level await so that asynchronous tasks initiated during execution environment initialization are completed during initialization. Asynchronous tasks that are not completed during initialization will typically run during the first function invoke. This can cause unexpected behavior or errors. For example, your function initialization may make a network call to fetch a parameter from AWS Parameter Store. If this task is not completed during initialization, the value may be null during an invocation. There can also be a delay between initialization and invoke which can trigger errors in time-sensitive operations. In particular, AWS service calls can rely on time-sensitive request signatures, resulting in service call failures if the call is not completed during the initialization phase. Completing tasks during initialization typically improves cold-start performance, and first invoke performance when using Provisioned Concurrency. For more information, see our blog post [Using Node.js ES modules and top-level await in AWS Lambda](https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda).
+
@@ -207 +225 @@ The examples in this section use the `S3Event` type. However, you can use any ot
-### Using async/await (recommended)
+### async function handlers (recommended)
@@ -220 +237,0 @@ Here are the valid signatures for the async/await pattern:
-  * **Event only:**
@@ -224 +240,0 @@ Here are the valid signatures for the async/await pattern:
-  * **Event and context object:**
@@ -227,0 +244 @@ Here are the valid signatures for the async/await pattern:
+###### Note
@@ -228,0 +246 @@ Here are the valid signatures for the async/await pattern:
+When processing arrays of items asynchronously, make sure to use await with `Promise.all` to ensure all operations complete. Methods like `forEach` don't wait for async callbacks to complete. For more information, see [Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) in the Mozilla documentation.
@@ -229,0 +248 @@ Here are the valid signatures for the async/await pattern:
+### Synchronous function handlers
@@ -231 +250 @@ Here are the valid signatures for the async/await pattern:
-###### Note
+Where your function does not perform any asynchronous tasks, you can use a synchronous function handler, using one of the following function signatures:
@@ -233 +251,0 @@ Here are the valid signatures for the async/await pattern:
-When processing arrays of items asynchronously, make sure to use await with `Promise.all` to ensure all operations complete. Methods like `forEach` don't wait for async callbacks to complete. For more information, see [Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) in the Mozilla documentation.
@@ -235 +253 @@ When processing arrays of items asynchronously, make sure to use await with `Pro
-### Using callbacks
+    export const handler = (event: S3Event): void => { };
@@ -237 +254,0 @@ When processing arrays of items asynchronously, make sure to use await with `Pro
-Callback handlers can use the event, context, and callback arguments. The callback argument expects an `Error` and a response, which must be JSON-serializable.
@@ -239 +256 @@ Callback handlers can use the event, context, and callback arguments. The callba
-Here are the valid signatures for the callback handler pattern:
+    export const handler = (event: S3Event, context: Context): void => { };
@@ -241 +258 @@ Here are the valid signatures for the callback handler pattern:
-  * **Event and callback object:**
+### Response streaming function handlers
@@ -243 +260 @@ Here are the valid signatures for the callback handler pattern:
-        export const handler = (event: S3Event, callback: Callback<void>): void => { };
+Lambda supports response streaming with Node.js. Response streaming function handlers use the awslambda.streamifyResponse() decorator and take 3 parameters: event, responseStream, and context. The function signature is:
@@ -245 +261,0 @@ Here are the valid signatures for the callback handler pattern:
-  * **Event, context, and callback objects:**
@@ -247 +263,5 @@ Here are the valid signatures for the callback handler pattern:
-        export const handler = (event: S3Event, context: Context, callback: Callback<void>): void => { };
+    export const handler = awslambda.streamifyResponse(async (event: APIGatewayProxyEvent, responseStream: NodeJS.WritableStream, context: Context) => { });
+
+For more information, see Response streaming for Lambda functions.
+
+### Callback-based function handlers
@@ -248,0 +269,5 @@ Here are the valid signatures for the callback handler pattern:
+###### Note
+
+Callback-based function handlers are only supported up to Node.js 22. Starting from Node.js 24, asynchronous tasks should be implemented using async function handlers.
+
+Callback-based function handlers can use the event, context, and callback arguments. The callback argument expects an `Error` and a response, which must be JSON-serializable.
@@ -249,0 +275 @@ Here are the valid signatures for the callback handler pattern:
+Here is the valid signature for the callback handler pattern:
@@ -252 +278,3 @@ Here are the valid signatures for the callback handler pattern:
-The function continues to execute until the [event loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/) is empty or the function times out. The response isn't sent to the invoker until all event loop tasks are finished. If the function times out, an error is returned instead. You can configure the runtime to send the response immediately by setting [context.callbackWaitsForEmptyEventLoop](./nodejs-context.html) to false.
+    export const handler = (event: S3Event, context: Context, callback: Callback<void>): void => { };
+
+The function continues to execute until the [event loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/) is empty or the function times out. The response isn't sent to the invoker until all event loop tasks are finished. If the function times out, an error is returned instead. You can configure the runtime to send the response immediately by setting [context.callbackWaitsForEmptyEventLoop](./typescript-context.html) to false.