

# Response streaming for Lambda functions
<a name="configuration-response-streaming"></a>

Lambda functions can natively stream response payloads back to clients through [Lambda function URLs](urls-configuration.md) or by using the [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API (via the AWS SDK or direct API calls). Your Lambda function can also stream response payloads through the [Amazon API Gateway proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/response-transfer-mode-lambda.html), which uses the [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API to invoke your function. Response streaming can benefit latency sensitive applications by improving time to first byte (TTFB) performance. This is because you can send partial responses back to the client as they become available. Additionally, response streaming functions can return payloads up to 200 MB, compared to the 6 MB maximum for buffered responses. Streaming a response also means that your function doesn’t need to fit the entire response in memory. For very large responses, this can reduce the amount of memory you need to configure for your function. 

**Note**  
Lambda response streaming is not yet available in all AWS Regions. Please refer to Builder Center's [AWS Capabilities by Region](https://builder.aws.com/build/capabilities) for feature availability by Region.

The speed at which Lambda streams your responses depends on the response size. The streaming rate for the first 6 MB of your function’s response is uncapped. For responses larger than 6 MB, the remainder of the response is subject to a bandwidth cap. For more information on streaming bandwidth, see [Bandwidth limits for response streaming](#config-rs-bandwidth-cap).

Streaming responses incur cost and streamed responses are not interrupted or stopped when the invoking client connection is broken. Customers will be billed for the full function duration, so customers should exercise caution when configuring long function timeouts.

Lambda supports response streaming on Node.js managed runtimes. For other languages, including Python, you can [use a custom runtime with a custom Runtime API integration](runtimes-custom.md#runtimes-custom-response-streaming) to stream responses or use the [Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter).

**Note**  
When testing your function through the Lambda console, you'll always see responses as buffered.

**Topics**
+ [

## Bandwidth limits for response streaming
](#config-rs-bandwidth-cap)
+ [

## VPC compatibility with response streaming
](#config-rs-vpc-compatibility)
+ [

# Writing response streaming-enabled Lambda functions
](config-rs-write-functions.md)
+ [

# Invoking a response streaming enabled function using Lambda function URLs
](config-rs-invoke-furls.md)
+ [

# Tutorial: Creating a response streaming Lambda function with a function URL
](response-streaming-tutorial.md)

## Bandwidth limits for response streaming
<a name="config-rs-bandwidth-cap"></a>

The first 6 MB of your function’s response payload has uncapped bandwidth. After this initial burst, Lambda streams your response at a maximum rate of 2 MBps. If your function responses never exceed 6 MB, then this bandwidth limit never applies. 

**Note**  
Bandwidth limits only apply to your function’s response payload, and not to network access by your function.

The rate of uncapped bandwidth varies depending on a number of factors, including your function’s processing speed. You can normally expect a rate higher than 2 MBps for the first 6 MB of your function’s response. If your function is streaming a response to a destination outside of AWS, the streaming rate also depends on the speed of the external internet connection. 

## VPC compatibility with response streaming
<a name="config-rs-vpc-compatibility"></a>

When using Lambda functions in a VPC environment, there are important considerations for response streaming:
+ Lambda function URLs do not support response streaming within a VPC environment.
+ You can use response streaming within a VPC by invoking your Lambda function through the AWS SDK using the `InvokeWithResponseStream` API. This requires setting up the appropriate VPC endpoints for Lambda.
+ For VPC environments, you'll need to create an interface VPC endpoint for Lambda to enable communication between your resources in the VPC and the Lambda service.

A typical architecture for response streaming in a VPC might include:

```
Client in VPC -> Interface VPC endpoint for Lambda -> Lambda function -> Response streaming back through the same path
```

# Writing response streaming-enabled Lambda functions
<a name="config-rs-write-functions"></a>

Writing the handler for response streaming functions is different than typical handler patterns. When writing streaming functions, be sure to do the following:
+ Wrap your function with the `awslambda.streamifyResponse()` decorator. The `awslambda` global object is provided by Lambda's Node.js runtime environment.
+ End the stream gracefully to ensure that all data processing is complete.

## Configuring a handler function to stream responses
<a name="config-rs-write-functions-handler"></a>

To indicate to the runtime that Lambda should stream your function's responses, you must wrap your function with the `streamifyResponse()` decorator. This tells the runtime to use the proper logic path for streaming responses and enables the function to stream responses.

The `streamifyResponse()` decorator accepts a function that accepts the following parameters:
+ `event` – Provides information about the function URL's invocation event, such as the HTTP method, query parameters, and the request body.
+ `responseStream` – Provides a writable stream.
+ `context` – Provides methods and properties with information about the invocation, function, and execution environment.

The `responseStream` object is a [Node.js `writableStream`](https://nodesource.com/blog/understanding-streams-in-nodejs/). As with any such stream, you should use the `pipeline()` method.

**Note**  
The `awslambda` global object is automatically provided by Lambda's Node.js runtime and no import is required.

**Example response streaming-enabled handler**  

```
import { pipeline } from 'node:stream/promises';
import { Readable } from 'node:stream';

export const echo = awslambda.streamifyResponse(async (event, responseStream, _context) => {
  // As an example, convert event to a readable stream.
  const requestStream = Readable.from(Buffer.from(JSON.stringify(event)));

  await pipeline(requestStream, responseStream);
});
```

While `responseStream` offers the `write()` method to write to the stream, we recommend that you use [https://nodejs.org/api/stream.html#streampipelinesource-transforms-destination-callback](https://nodejs.org/api/stream.html#streampipelinesource-transforms-destination-callback) wherever possible. Using `pipeline()` ensures that the writable stream is not overwhelmed by a faster readable stream.

## Ending the stream
<a name="config-rs-write-functions-end"></a>

Make sure that you properly end the stream before the handler returns. The `pipeline()` method handles this automatically.

For other use cases, call the `responseStream.end()` method to properly end a stream. This method signals that no more data should be written to the stream. This method isn't required if you write to the stream with `pipeline()` or `pipe()`.

Starting with Node.js 24, Lambda no longer waits for unresolved promises to complete after your handler returns or the response stream ends. If your function depends on additional asynchronous operations, such as timers or fetches, you should `await` them in your handler.

**Example ending a stream with pipeline()**  

```
import { pipeline } from 'node:stream/promises';

export const handler = awslambda.streamifyResponse(async (event, responseStream, _context) => {
  await pipeline(requestStream, responseStream);
});
```

**Example ending a stream without pipeline()**  

```
export const handler = awslambda.streamifyResponse(async (event, responseStream, _context) => {
  responseStream.write("Hello ");
  responseStream.write("world ");
  responseStream.write("from ");
  responseStream.write("Lambda!");
  responseStream.end();
});
```

# Invoking a response streaming enabled function using Lambda function URLs
<a name="config-rs-invoke-furls"></a>

**Note**  
Your Lambda function can now stream response payloads through the [Amazon API Gateway proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/response-transfer-mode-lambda.html).

You can invoke response streaming enabled functions by changing the invoke mode of your function's URL. The invoke mode determines which API operation Lambda uses to invoke your function. The available invoke modes are:
+ `BUFFERED` – This is the default option. Lambda invokes your function using the `Invoke` API operation. Invocation results are available when the payload is complete. The maximum payload size is 6 MB.
+ `RESPONSE_STREAM` – Enables your function to stream payload results as they become available. Lambda invokes your function using the `InvokeWithResponseStream` API operation. The maximum response payload size is 200 MB.

You can still invoke your function without response streaming by directly calling the `Invoke` API operation. However, Lambda streams all response payloads for invocations that come through the function's URL until you change the invoke mode to `BUFFERED`.

------
#### [ Console ]

**To set the invoke mode of a function URL (console)**

1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console.

1. Choose the name of the function that you want to set the invoke mode for.

1. Choose the **Configuration** tab, and then choose **Function URL**.

1. Choose **Edit**, then choose **Additional settings**.

1. Under **Invoke mode**, choose your desired invoke mode.

1. Choose **Save**.

------
#### [ AWS CLI ]

**To set the invoke mode of a function's URL (AWS CLI)**

```
aws lambda update-function-url-config \
  --function-name my-function \
  --invoke-mode RESPONSE_STREAM
```

------
#### [ CloudFormation ]

**To set the invoke mode of a function's URL (CloudFormation)**

```
MyFunctionUrl:
  Type: AWS::Lambda::Url
  Properties:
    AuthType: AWS_IAM
    InvokeMode: RESPONSE_STREAM
```

------

For more information about configuring function URLs, see [Lambda function URLs](urls-configuration.md).

# Tutorial: Creating a response streaming Lambda function with a function URL
<a name="response-streaming-tutorial"></a>

In this tutorial, you create a Lambda function defined as a .zip file archive with a function URL endpoint that returns a response stream. For more information about configuring function URLs, see [Function URLs](urls-configuration.md).

## Prerequisites
<a name="response-streaming-prepare"></a>

This tutorial assumes that you have some knowledge of basic Lambda operations and the Lambda console. If you haven't already, follow the instructions in [Create a Lambda function with the console](getting-started.md#getting-started-create-function) to create your first Lambda function.

To complete the following steps, you need the [AWS CLI version 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). Commands and the expected output are listed in separate blocks:

```
aws --version
```

You should see the following output:

```
aws-cli/2.13.27 Python/3.11.6 Linux/4.14.328-248.540.amzn2.x86_64 exe/x86_64.amzn.2
```

For long commands, an escape character (`\`) is used to split a command over multiple lines.

On Linux and macOS, use your preferred shell and package manager.

**Note**  
In Windows, some Bash CLI commands that you commonly use with Lambda (such as `zip`) are not supported by the operating system's built-in terminals. To get a Windows-integrated version of Ubuntu and Bash, [install the Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). Example CLI commands in this guide use Linux formatting. Commands which include inline JSON documents must be reformatted if you are using the Windows CLI. 

## Create an execution role
<a name="response-streaming-create-iam-role"></a>

Create the [execution role](lambda-intro-execution-role.md) that gives your Lambda function permission to access AWS resources.

**To create an execution role**

1. Open the [Roles page](https://console.aws.amazon.com/iam/home#/roles) of the AWS Identity and Access Management (IAM) console.

1. Choose **Create role**.

1. Create a role with the following properties:
   + **Trusted entity type** – **AWS service**
   + **Use case** – **Lambda**
   + **Permissions** – **AWSLambdaBasicExecutionRole**
   + **Role name** – **response-streaming-role**

The **AWSLambdaBasicExecutionRole** policy has the permissions that the function needs to write logs to Amazon CloudWatch Logs. After you create the role, note down the its Amazon Resource Name (ARN). You'll need it in the next step.

## Create a response streaming function (AWS CLI)
<a name="response-streaming-tutorial-create-function-cli"></a>

Create a response streaming Lambda function with a function URL endpoint using the AWS Command Line Interface (AWS CLI).

**To create a function that can stream responses**

1. Copy the following code example into a file named `index.js`. This function streams three responses, separated by 1 second.

   ```
   exports.handler = awslambda.streamifyResponse(
   	async (event, responseStream, _context) => {
   		// Metadata is a JSON serializable JS object. Its shape is not defined here.
   		const metadata = {
   		statusCode: 200,
   		headers: {
   			"Content-Type": "application/json",
   			"CustomHeader": "outerspace"
   		}
   		};
   	
   		// Assign to the responseStream parameter to prevent accidental reuse of the non-wrapped stream.
   		responseStream = awslambda.HttpResponseStream.from(responseStream, metadata);
   	
   		responseStream.write("Streaming with Helper \n");
   		await new Promise(r => setTimeout(r, 1000));
   		responseStream.write("Hello 0 \n");
   		await new Promise(r => setTimeout(r, 1000));
   		responseStream.write("Hello 1 \n");
   		await new Promise(r => setTimeout(r, 1000));
   		responseStream.write("Hello 2 \n");
   		await new Promise(r => setTimeout(r, 1000));
   		responseStream.end();
   		await responseStream.finished();
   	}
     );
   ```

1. Create a deployment package.

   ```
   zip function.zip index.js
   ```

1. Create a Lambda function with the `create-function` command. Replace the value of `--role` with the role ARN from the previous step. This command sets the function timeout to 10 seconds, which allows the function to stream three responses.

   ```
   aws lambda create-function \
     --function-name my-streaming-function \
     --runtime nodejs24.x \
     --zip-file fileb://function.zip \
     --handler index.handler \
     --timeout 10 \
     --role arn:aws:iam::123456789012:role/response-streaming-role
   ```

**To create a function URL**

1. Add a resource-based policy to your function that grants `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions. Each statement must be added in a separate command. Replace the value of `--principal` with your AWS account ID.

   ```
   aws lambda add-permission \
     --function-name my-streaming-function \
     --action lambda:InvokeFunctionUrl \
     --statement-id UrlPolicyInvokeURL \
     --principal 123456789012 \
     --function-url-auth-type AWS_IAM
   ```

   ```
   aws lambda add-permission \
       --function-name my-streaming-function \
       --action lambda:InvokeFunction \
       --statement-id UrlPolicyInvokeFunction \
       --principal 123456789012
   ```

1. Create a URL endpoint for the function with the `create-function-url-config` command.

   ```
   aws lambda create-function-url-config \
     --function-name my-streaming-function \
     --auth-type AWS_IAM \
     --invoke-mode RESPONSE_STREAM
   ```
**Note**  
If you get an error about `--invoke-mode`, you might need to upgrade to a [newer version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).

## Test the function URL endpoint
<a name="response-streaming-tutorial-test"></a>

Test your integration by invoking your function. You can open your function's URL in a browser, or you can use curl.

```
curl --request GET "https://abcdefghijklm7nop7qrs740abcd.lambda-url.us-east-1.on.aws/" --user "AKIAIOSFODNN7EXAMPLE" --aws-sigv4 "aws:amz:us-east-1:lambda" --no-buffer
```

Our function URL uses the `IAM_AUTH` authentication type. This means that you need to sign requests with both your [AWS access key and secret key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). In the previous command, replace `AKIAIOSFODNN7EXAMPLE` with the AWS access key ID. Enter your AWS secret key when prompted. If you don't have your AWS secret key, you can [use temporary AWS credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) instead.

You should see a response like this:

```
Streaming with Helper 
Hello 0 
Hello 1
Hello 2
```

## Clean up your resources
<a name="cleanup"></a>

You can now delete the resources that you created for this tutorial, unless you want to retain them. By deleting AWS resources that you're no longer using, you prevent unnecessary charges to your AWS account.

**To delete the execution role**

1. Open the [Roles page](https://console.aws.amazon.com/iam/home#/roles) of the IAM console.

1. Select the execution role that you created.

1. Choose **Delete**.

1. Enter the name of the role in the text input field and choose **Delete**.

**To delete the Lambda function**

1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console.

1. Select the function that you created.

1. Choose **Actions**, **Delete**.

1. Type **confirm** in the text input field and choose **Delete**.