

# Understanding Lambda function invocation methods
<a name="lambda-invocation"></a>

After you deploy your Lambda function, you can invoke it in several ways:
+ The [Lambda console](testing-functions.md) – Use the Lambda console to quickly create a test event to invoke your function.
+ The [AWS SDK](https://aws.amazon.com/developer/tools/) – Use the AWS SDK to programmatically invoke your function.
+ The [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) API – Use the Lambda Invoke API to directly invoke your function.
+ The [AWS Command Line Interface (AWS CLI)](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) – Use the `aws lambda invoke` AWS CLI command to directly invoke your function from the command line.
+ A [function URL HTTP(S) endpoint](urls-configuration.md) – Use function URLs to create a dedicated HTTP(S) endpoint that you can use to invoke your function.

All of these methods are *direct* ways to invoke your function. In Lambda, a common use case is to invoke your function based on an event that occurs elsewhere in your application. Some services can invoke a Lambda function with each new event. This is called a [trigger](lambda-services.md). For stream and queue-based services, Lambda invokes the function with batches of records. This is called an [event source mapping](invocation-eventsourcemapping.md).

When you invoke a function, you can choose to invoke it synchronously or asynchronously. With [synchronous invocation](invocation-sync.md), you wait for the function to process the event and return a response. With [asynchronous invocation](invocation-async.md), Lambda queues the event for processing and returns a response immediately. The [`InvocationType` request parameter in the Invoke API](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#API_Invoke_RequestParameters) determines how Lambda invokes your function. A value of `RequestResponse` indicates synchronous invocation, and a value of `Event` indicates asynchronous invocation.

To invoke your function over IPv6, use Lambda's public [dual-stack endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#dual-stack-endpoints). Dual-stack endpoints support both IPv4 and IPv6. Lambda dual-stack endpoints use the following syntax:

```
protocol://lambda.us-east-1.api.aws
```

You can also use [Lambda function URLs](urls-configuration.md) to invoke functions over IPv6. Function URL endpoints have the following format:

```
https://url-id.lambda-url.us-east-1.on.aws
```

If the function invocation results in an error, for synchronous invocations, view the error message in the response and retry the invocation manually. For asynchronous invocations, Lambda handles retries automatically and can send invocation records to a [destination](invocation-async-retain-records.md#invocation-async-destinations).

# Invoke a Lambda function synchronously
<a name="invocation-sync"></a>

When you invoke a function synchronously, Lambda runs the function and waits for a response. When the function completes, Lambda returns the response from the function's code with additional data, such as the version of the function that was invoked. To invoke a function synchronously with the AWS CLI, use the `invoke` command.

```
aws lambda invoke --function-name my-function \
    --cli-binary-format raw-in-base64-out \
    --payload '{ "key": "value" }' response.json
```

The **cli-binary-format** option is required if you're using AWS CLI version 2. To make this the default setting, run `aws configure set cli-binary-format raw-in-base64-out`. For more information, see [AWS CLI supported global command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) in the *AWS Command Line Interface User Guide for Version 2*.

You should see the following output:

```
{
    "ExecutedVersion": "$LATEST",
    "StatusCode": 200
}
```

The following diagram shows clients invoking a Lambda function synchronously. Lambda sends the events directly to the function and sends the function's response back to the invoker.

![\[\]](http://docs.aws.amazon.com/lambda/latest/dg/images/invocation-sync.png)


The `payload` is a string that contains an event in JSON format. The name of the file where the AWS CLI writes the response from the function is `response.json`. If the function returns an object or error, the response body is the object or error in JSON format. If the function exits without error, the response body is `null`.

**Note**  
Lambda does not wait for external extensions to complete before sending the response. External extensions run as independent processes in the execution environment and continue to run after the function invocation is complete. For more information, see [Augment Lambda functions using Lambda extensions](lambda-extensions.md).

The output from the command, which is displayed in the terminal, includes information from headers in the response from Lambda. This includes the version that processed the event (useful when you use [aliases](configuration-aliases.md)), and the status code returned by Lambda. If Lambda was able to run the function, the status code is 200, even if the function returned an error.

**Note**  
For functions with a long timeout, your client might be disconnected during synchronous invocation while it waits for a response. Configure your HTTP client, SDK, firewall, proxy, or operating system to allow for long connections with timeout or keep-alive settings.

If Lambda isn't able to run the function, the error is displayed in the output.

```
aws lambda invoke --function-name my-function \
    --cli-binary-format raw-in-base64-out \
    --payload value response.json
```

You should see the following output:

```
An error occurred (InvalidRequestContentException) when calling the Invoke operation: Could not parse request body into json: Unrecognized token 'value': was expecting ('true', 'false' or 'null')
 at [Source: (byte[])"value"; line: 1, column: 11]
```

The AWS CLI is an open-source tool that enables you to interact with AWS services using commands in your command line shell. To complete the steps in this section, you must have the [AWS CLI version 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).

You can use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) to retrieve logs for an invocation using the `--log-type` command option. The response contains a `LogResult` field that contains up to 4 KB of base64-encoded logs from the invocation.

**Example retrieve a log ID**  
The following example shows how to retrieve a *log ID* from the `LogResult` field for a function named `my-function`.  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
You should see the following output:  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example decode the logs**  
In the same command prompt, use the `base64` utility to decode the logs. The following example shows how to retrieve base64-encoded logs for `my-function`.  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
The **cli-binary-format** option is required if you're using AWS CLI version 2. To make this the default setting, run `aws configure set cli-binary-format raw-in-base64-out`. For more information, see [AWS CLI supported global command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) in the *AWS Command Line Interface User Guide for Version 2*.  
You should see the following output:  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
The `base64` utility is available on Linux, macOS, and [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10). macOS users may need to use `base64 -D`.

For more information about the `Invoke` API, including a full list of parameters, headers, and errors, see [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html).

When you invoke a function directly, you can check the response for errors and retry. The AWS CLI and AWS SDK also automatically retry on client timeouts, throttling, and service errors. For more information, see [Understanding retry behavior in Lambda](invocation-retries.md).

# Invoking a Lambda function asynchronously
<a name="invocation-async"></a>

Several AWS services, such as Amazon Simple Storage Service (Amazon S3) and Amazon Simple Notification Service (Amazon SNS), invoke functions asynchronously to process events. You can also invoke a Lambda function asynchronously using the AWS Command Line Interface (AWS CLI) or one of the AWS SDKs. When you invoke a function asynchronously, you don't wait for a response from the function code. You hand off the event to Lambda and Lambda handles the rest. You can configure how Lambda handles errors, and can send invocation records to a downstream resource such as Amazon Simple Queue Service (Amazon SQS) or Amazon EventBridge (EventBridge) to chain together components of your application.

The following diagram shows clients invoking a Lambda function asynchronously. Lambda queues the events before sending them to the function.

![\[\]](http://docs.aws.amazon.com/lambda/latest/dg/images/features-async.png)


For asynchronous invocation, Lambda places the event in a queue and returns a success response without additional information. A separate process reads events from the queue and sends them to your function.

 To invoke a Lambda function asynchronously using the AWS Command Line Interface (AWS CLI) or one of the AWS SDKs, set the [InvocationType](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#lambda-Invoke-request-InvocationType) parameter to `Event`. The following example shows an AWS CLI command to invoke a function.

```
aws lambda invoke \
  --function-name my-function  \
  --invocation-type Event \
  --cli-binary-format raw-in-base64-out \
  --payload '{ "key": "value" }' response.json
```

You should see the following output:

```
{
    "StatusCode": 202
}
```

The **cli-binary-format** option is required if you're using AWS CLI version 2. To make this the default setting, run `aws configure set cli-binary-format raw-in-base64-out`. For more information, see [AWS CLI supported global command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) in the *AWS Command Line Interface User Guide for Version 2*.

The output file (`response.json`) doesn't contain any information, but is still created when you run this command. If Lambda isn't able to add the event to the queue, the error message appears in the command output.

# How Lambda handles errors and retries with asynchronous invocation
<a name="invocation-async-error-handling"></a>

Lambda manages your function's asynchronous event queue and attempts to retry on errors. If the function returns an error, by default Lambda attempts to run it two more times, with a one-minute wait between the first two attempts, and two minutes between the second and third attempts. Function errors include errors returned by the function's code and errors returned by the function's runtime, such as timeouts.

If the function doesn't have enough concurrency available to process all events, additional requests are throttled. For throttling errors (429) and system errors (500-series), Lambda returns the event to the queue and attempts to run the function again for up to 6 hours by default. The retry interval increases exponentially from 1 second after the first attempt to a maximum of 5 minutes. If the queue contains many entries, Lambda increases the retry interval and reduces the rate at which it reads events from the queue.

Even if your function doesn't return an error, it's possible for it to receive the same event from Lambda multiple times because the queue itself is eventually consistent. If the function can't keep up with incoming events, events might also be deleted from the queue without being sent to the function. Ensure that your function code gracefully handles duplicate events, and that you have enough concurrency available to handle all invocations.

When the queue is very long, new events might age out before Lambda has a chance to send them to your function. When an event expires or fails all processing attempts, Lambda discards it. You can [configure error handling](invocation-async-configuring.md) for a function to reduce the number of retries that Lambda performs, or to discard unprocessed events more quickly. To capture discarded events, [configure a dead-letter queue](invocation-async-retain-records.md#invocation-dlq) for the function. To capture records of failed invocations (such as timeouts or runtime errors), [create an on-failure destination](invocation-async-retain-records.md#invocation-async-destinations). 

# Configuring error handling settings for Lambda asynchronous invocations
<a name="invocation-async-configuring"></a>

Use the following settings to configure how Lambda handles errors and retries for asynchronous function invocations:
+ [MaximumEventAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html#lambda-PutFunctionEventInvokeConfig-request-MaximumEventAgeInSeconds): The maximum amount of time, in seconds, that Lambda keeps an event in the asynchronous event queue before discarding it.
+ [MaximumRetryAttempts](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html#lambda-PutFunctionEventInvokeConfig-request-MaximumRetryAttempts): The maximum number of times that Lambda retries events when the function returns an error.

Use the Lambda console or AWS CLI to configure error handling settings on a function, a version, or an alias.

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

**To configure error handling**

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

1. Choose a function.

1. Choose **Configuration** and then choose **Asynchronous invocation**.

1. Under **Asynchronous invocation**, choose **Edit**.

1. Configure the following settings.
   + **Maximum age of event** – The maximum amount of time Lambda retains an event in the asynchronous event queue, up to 6 hours.
   + **Retry attempts** – The number of times Lambda retries when the function returns an error, between 0 and 2.

1. Choose **Save**.

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

To configure asynchronous invocation with the AWS CLI, use the [put-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/put-function-event-invoke-config.html) command. The following example configures a function with a maximum event age of 1 hour and no retries.

```
aws lambda put-function-event-invoke-config \ 
  --function-name error \
  --maximum-event-age-in-seconds 3600 \
  --maximum-retry-attempts 0
```

The `put-function-event-invoke-config` command overwrites any existing configuration on the function, version, or alias. To configure an option without resetting others, use [update-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-event-invoke-config.html). The following example configures Lambda to send a record to a standard SQS queue named `destination` when an event can't be processed.

```
aws lambda update-function-event-invoke-config \
  --function-name my-function \
  --destination-config '{"OnFailure":{"Destination": "arn:aws:sqs:us-east-1:123456789012:destination"}}'
```

------

You should see the following output:

```
{
    "LastModified": 1573686021.479,
    "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST",
    "MaximumRetryAttempts": 0,
    "MaximumEventAgeInSeconds": 3600,
    "DestinationConfig": {
        "OnSuccess": {},
        "OnFailure": {}
    }
}
```

When an invocation event exceeds the maximum age or fails all retry attempts, Lambda discards it. To retain a copy of discarded events, configure a failed-event [destination](invocation-async-retain-records.md#invocation-async-destinations).

# Capturing records of Lambda asynchronous invocations
<a name="invocation-async-retain-records"></a>

Lambda can send records of asynchronous invocations to one of the following AWS services.
+ **Amazon SQS** – A standard SQS queue
+ **Amazon SNS** – A standard SNS topic
+ **Amazon S3** – An Amazon S3 bucket (on failure only)
+ **AWS Lambda** – A Lambda function
+ **Amazon EventBridge** – An EventBridge event bus

The invocation record contains details about the request and response in JSON format. You can configure separate destinations for events that are processed successfully, and events that fail all processing attempts. Alternatively, you can configure a standard Amazon SQS queue or standard Amazon SNS topic as a dead-letter queue for discarded events. For dead-letter queues, Lambda only sends the content of the event, without details about the response.

If Lambda can't send a record to a destination you have configured, it sends a `DestinationDeliveryFailures` metric to Amazon CloudWatch. This can happen if your configuration includes an unsupported destination type, such as an Amazon SQS FIFO queue or an Amazon SNS FIFO topic. Delivery errors can also occur due to permissions errors and size limits. For more information on Lambda invocation metrics, see [Invocation metrics](monitoring-metrics-types.md#invocation-metrics).

**Note**  
To prevent a function from triggering, you can set the function's reserved concurrency to zero. When you set reserved concurrency to zero for an asynchronously invoked function, Lambda begins sending new events to the configured [dead-letter queue](#invocation-dlq) or the on-failure [event destination](#invocation-async-destinations), without any retries. To process events that were sent while reserved concurrency was set to zero, you must consume the events from the dead-letter queue or the on-failure event destination.

## Adding a destination
<a name="invocation-async-destinations"></a>

To retain records of asynchronous invocations, add a destination to your function. You can choose to send either successful or failed invocations to a destination. Each function can have multiple destinations, so you can configure separate destinations for successful and failed events. Each record sent to the destination is a JSON document with details about the invocation. Like error handling settings, you can configure destinations on a function, function version, or alias.

**Tip**  
You can also retain records of failed invocations for the following event source mapping types: [Amazon Kinesis](kinesis-on-failure-destination.md#kinesis-on-failure-destination-console), [Amazon DynamoDB](services-dynamodb-errors.md), and [Apache Kafka (Amazon MSK and self-managed Apache Kafka)](kafka-on-failure.md#kafka-onfailure-destination).<a name="destinations-permissions"></a>

The following table lists supported destinations for asynchronous invocation records. For Lambda to successfully send records to your chosen destination, ensure that your function's [execution role](lambda-intro-execution-role.md) also contains the relevant permissions. The table also describes how each destination type receives the JSON invocation record.


| Destination type | Required permission | Destination-specific JSON format | 
| --- | --- | --- | 
|  Amazon SQS queue  |  [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)  |  Lambda passes the invocation record as the `Message` to the destination.  | 
|  Amazon SNS topic  |  [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)  |  Lambda passes the invocation record as the `Message` to the destination.  | 
|  Amazon S3 bucket (on failure only)  |  [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html)  | 
|  Lambda function  |  [lambda:InvokeFunction](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  Lambda passes the invocation record as the payload to the function.  | 
|  EventBridge  |  [events:PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html)  | 

**Note**  
For Amazon S3 destinations, if you have enabled encryption on the bucket using a KMS key, your function also needs the [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) permission.

**Important**  
When using Amazon SNS as a destination, be aware that Amazon SNS has a maximum message size limit of 256 KB. If your async invocation payload approaches 1 MB, the invocation record (which includes the original payload plus additional metadata) may exceed the Amazon SNS limit and cause delivery failures. Consider using Amazon SQS or Amazon S3 destinations for larger payloads.

The following steps describe how to configure a destination for a function using the Lambda console and the AWS CLI.

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

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

1. Choose a function.

1. Under **Function overview**, choose **Add destination**.

1. For **Source**, choose **Asynchronous invocation**.

1. For **Condition**, choose from the following options:
   + **On failure** – Send a record when the event fails all processing attempts or exceeds the maximum age.
   + **On success** – Send a record when the function successfully processes an asynchronous invocation.

1. For **Destination type**, choose the type of resource that receives the invocation record.

1. For **Destination**, choose a resource.

1. Choose **Save**.

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

To configure a destination using the AWS CLI, run the [update-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-event-invoke-config.html) command. The following example configures Lambda to send a record to a standard SQS queue named `destination` when an event can't be processed.

```
aws lambda update-function-event-invoke-config \
  --function-name my-function \
  --destination-config '{"OnFailure":{"Destination": "arn:aws:sqs:us-east-1:123456789012:destination"}}'
```

------

### Security best practices for Amazon S3 destinations
<a name="s3-destination-security"></a>

Deleting an S3 bucket that's configured as a destination without removing the destination from your function's configuration can create a security risk. If another user knows your destination bucket's name, they can recreate the bucket in their AWS account. Records of failed invocations will be sent to their bucket, potentially exposing data from your function.

**Warning**  
To ensure that invocation records from your function can't be sent to an S3 bucket in another AWS account, add a condition to your function's execution role that limits `s3:PutObject` permissions to buckets in your account. 

The following example shows an IAM policy that limits your function's `s3:PutObject` permissions to buckets in your account. This policy also gives Lambda the `s3:ListBucket` permission it needs to use an S3 bucket as a destination.

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "S3BucketResourceAccountWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::*/*",
                "arn:aws:s3:::*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:ResourceAccount": "111122223333"
                }
            }
        }
    ]
}
```

To add a permissions policy to your function's execution role using the AWS Management Console or AWS CLI, refer to the instructions in the following procedures:

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

**To add a permissions policy to a function's execution role (console)**

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

1. Select the Lambda function whose execution role you want to modify.

1. In the **Configuration** tab, select **Permissions**.

1. In the **Execution role** tab, select your function's **Role name** to open the role's IAM console page.

1. Add a permissions policy to the role by doing the following:

   1. In the **Permissions policies** pane, choose **Add permissions** and select **Create inline policy**.

   1. In **Policy editor**, select **JSON**.

   1. Paste the policy you want to add into the editor (replacing the existing JSON), and then choose **Next**.

   1. Under **Policy details**, enter a **Policy name**.

   1. Choose **Create policy**.

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

**To add a permissions policy to a function's execution role (CLI)**

1. Create a JSON policy document with the required permissions and save it in a local directory.

1. Use the IAM `put-role-policy` CLI command to add the permissions to your function's execution role. Run the following command from the directory you saved your JSON policy document in and replace the role name, policy name, and policy document with your own values.

   ```
   aws iam put-role-policy \
   --role-name my_lambda_role \
   --policy-name LambdaS3DestinationPolicy \
   --policy-document file://my_policy.json
   ```

------

### Example invocation record
<a name="destination-example-record"></a>

When an invocation matches the condition, Lambda sends [a JSON document](#destinations-permissions) with details about the invocation to the destination. The following example shows an invocation record for an event that failed three processing attempts due to a function error.

**Example**  

```
{
    "version": "1.0",
    "timestamp": "2019-11-14T18:16:05.568Z",
    "requestContext": {
        "requestId": "e4b46cbf-b738-xmpl-8880-a18cdf61200e",
        "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST",
        "condition": "RetriesExhausted",
        "approximateInvokeCount": 3
    },
    "requestPayload": {
        "ORDER_IDS": [
            "9e07af03-ce31-4ff3-xmpl-36dce652cb4f",
            "637de236-e7b2-464e-xmpl-baf57f86bb53",
            "a81ddca6-2c35-45c7-xmpl-c3a03a31ed15"
        ]
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "responsePayload": {
        "errorMessage": "RequestId: e4b46cbf-b738-xmpl-8880-a18cdf61200e Process exited before completing request"
    }
}
```

The invocation record contains details about the event, the response, and the reason that the record was sent.

### Tracing requests to destinations
<a name="destinations-tracing"></a>

You can use AWS X-Ray to see a connected view of each request as it's queued, processed by a Lambda function, and passed to the destination service. When you activate X-Ray tracing for a function or a service that invokes a function, Lambda adds an X-Ray header to the request and passes the header to the destination service. Traces from upstream services are automatically linked to traces from downstream Lambda functions and destination services, creating an end-to-end view of the entire application. For more information about tracing, see [Visualize Lambda function invocations using AWS X-Ray](services-xray.md).

## Adding a dead-letter queue
<a name="invocation-dlq"></a>

As an alternative to an [on-failure destination](#invocation-async-destinations), you can configure your function with a dead-letter queue to save discarded events for further processing. A dead-letter queue acts the same as an on-failure destination in that it is used when an event fails all processing attempts or expires without being processed. However, you can only add or remove a dead-letter queue at the function level. Function versions use the same dead-letter queue settings as the unpublished version (\$1LATEST). On-failure destinations also support additional targets and include details about the function's response in the invocation record.

To reprocess events in a dead-letter queue, you can set it as an [event source](invocation-eventsourcemapping.md) for your Lambda function. Alternatively, you can manually retrieve the events.

You can choose an Amazon SQS standard queue or Amazon SNS standard topic for your dead-letter queue. FIFO queues and Amazon SNS FIFO topics are not supported.
+ [Amazon SQS queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html) – A queue holds failed events until they're retrieved. Choose an Amazon SQS standard queue if you expect a single entity, such as a Lambda function or CloudWatch alarm, to process the failed event. For more information, see [Using Lambda with Amazon SQS](with-sqs.md).
+ [Amazon SNS topic](https://docs.aws.amazon.com/sns/latest/gsg/CreateTopic.html) – A topic relays failed events to one or more destinations. Choose an Amazon SNS standard topic if you expect multiple entities to act on a failed event. For example, you can configure a topic to send events to an email address, a Lambda function, and/or an HTTP endpoint. For more information, see [Invoking Lambda functions with Amazon SNS notifications](with-sns.md).

To send events to a queue or topic, your function needs additional permissions. Add a policy with the [ required permissions](#destinations-permissions) to your function's [execution role](lambda-intro-execution-role.md). If the target queue or topic is encrypted with a customer managed AWS KMS key, ensure that both your function's execution role and the key's [resource-based policy](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html) contains the relevant permissions.

After creating the target and updating your function's execution role, add the dead-letter queue to your function. You can configure multiple functions to send events to the same target.

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

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

1. Choose a function.

1. Choose **Configuration** and then choose **Asynchronous invocation**.

1. Under **Asynchronous invocation**, choose **Edit**.

1. Set **Dead-letter queue service** to **Amazon SQS** or **Amazon SNS**.

1. Choose the target queue or topic.

1. Choose **Save**.

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

To configure a dead-letter queue with the AWS CLI, use the [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) command.

```
aws lambda update-function-configuration \
  --function-name my-function \
  --dead-letter-config TargetArn=arn:aws:sns:us-east-1:123456789012:my-topic
```

------

Lambda sends the event to the dead-letter queue as-is, with additional information in attributes. You can use this information to identify the error that the function returned, or to correlate the event with logs or an AWS X-Ray trace.

**Dead-letter queue message attributes**
+ **RequestID** (String) – The ID of the invocation request. Request IDs appear in function logs. You can also use the X-Ray SDK to record the request ID on an attribute in the trace. You can then search for traces by request ID in the X-Ray console.
+ **ErrorCode** (Number) – The HTTP status code.
+ **ErrorMessage** (String) – The first 1 KB of the error message.

If Lambda can't send a message to the dead-letter queue, it deletes the event and emits the [DeadLetterErrors](monitoring-metrics-types.md) metric. This can happen because of lack of permissions, or if the total size of the message exceeds the limit for the target queue or topic. For example, say that an Amazon SNS notification with a body close to 1 MB in size triggers a function that results in an error. In that case, the event data that Amazon SNS adds, combined with the attributes that Lambda adds, can cause the message to exceed the maximum size allowed in the dead-letter queue.

If you're using Amazon SQS as an event source, configure a dead-letter queue on the Amazon SQS queue itself and not on the Lambda function. For more information, see [Using Lambda with Amazon SQS](with-sqs.md).

# Invoking durable Lambda functions
<a name="durable-invocation"></a>

Durable Lambda functions can be invoked using the same methods as default Lambda functions, but with important considerations for long-running executions. This section covers invocation patterns, execution management, and best practices for durable functions.

## Synchronous invocation limits
<a name="synchronous-invocation-limits"></a>

Synchronous invocations of durable Lambda functions are limited to 15 minutes, the same as default Lambda functions. If your durable function needs to run longer than 15 minutes, it must be invoked asynchronously.

**When to use synchronous invocation:** Use for durable functions that complete within 15 minutes and when you need immediate results, such as quick approval workflows or short data processing tasks.

## Asynchronous invocation for long-running workflows
<a name="asynchronous-invocation"></a>

For durable functions that may run longer than 15 minutes, use asynchronous invocation. This allows the function to continue running while your client receives an immediate acknowledgment.

------
#### [ TypeScript ]

```
import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";

const client = new LambdaClient({});

// Asynchronous invocation
const command = new InvokeCommand({
  FunctionName: "my-durable-function",
  InvocationType: "Event", // Asynchronous
  Payload: JSON.stringify({ orderId: "12345" })
});

await client.send(command);
```

------
#### [ Python ]

```
import boto3
import json

client = boto3.client('lambda')

# Asynchronous invocation
response = client.invoke(
    FunctionName='my-durable-function',
    InvocationType='Event',  # Asynchronous
    Payload=json.dumps({'order_id': '12345'})
)
```

------

## Execution management APIs
<a name="execution-management-apis"></a>

Lambda provides APIs to manage and monitor durable function executions, including listing executions, getting execution status, and stopping running executions.

------
#### [ TypeScript ]

```
// Get execution status
const statusCommand = new InvokeCommand({
  FunctionName: "my-durable-function",
  InvocationType: "RequestResponse",
  Payload: JSON.stringify({ 
    action: "getStatus", 
    executionId: "exec-123" 
  })
});

const result = await client.send(statusCommand);
```

------
#### [ Python ]

```
# Get execution status
response = client.invoke(
    FunctionName='my-durable-function',
    InvocationType='RequestResponse',
    Payload=json.dumps({
        'action': 'get_status',
        'execution_id': 'exec-123'
    })
)
```

------

# How Lambda processes records from stream and queue-based event sources
<a name="invocation-eventsourcemapping"></a>

An *event source mapping* is a Lambda resource that reads items from stream and queue-based services and invokes a function with batches of records. Within an event source mapping, resources called *event pollers* actively poll for new messages and invoke functions. By default, Lambda automatically scales event pollers, but for certain event source types, you can use [ provisioned mode](#invocation-eventsourcemapping-provisioned-mode) to control the minimum and maximum number of event pollers dedicated to your event source mapping.

The following services use event source mappings to invoke Lambda functions:
+ [Amazon DocumentDB (with MongoDB compatibility) (Amazon DocumentDB)](with-documentdb.md)
+ [Amazon DynamoDB](with-ddb.md)
+ [Amazon Kinesis](with-kinesis.md)
+ [Amazon MQ](with-mq.md)
+ [Amazon Managed Streaming for Apache Kafka (Amazon MSK)](with-msk.md)
+ [Self-managed Apache Kafka](with-kafka.md)
+ [Amazon Simple Queue Service (Amazon SQS)](with-sqs.md)

**Warning**  
Lambda event source mappings process each event at least once, and duplicate processing of records can occur. To avoid potential issues related to duplicate events, we strongly recommend that you make your function code idempotent. To learn more, see [How do I make my Lambda function idempotent](https://repost.aws/knowledge-center/lambda-function-idempotent) in the AWS Knowledge Center.

## How event source mappings differ from direct triggers
<a name="eventsourcemapping-trigger-difference"></a>

Some AWS services can directly invoke Lambda functions using *triggers*. These services push events to Lambda, and the function is invoked immediately when the specified event occurs. Triggers are suitable for discrete events and real-time processing. When you [create a trigger using the Lambda console](lambda-services.md#lambda-invocation-trigger), the console interacts with the corresponding AWS service to configure the event notification on that service. The trigger is actually stored and managed by the service that generates the events, not by Lambda. Here are some examples of services that use triggers to invoke Lambda functions:
+ **Amazon Simple Storage Service (Amazon S3):** Invokes a function when an object is created, deleted, or modified in a bucket. For more information, see [Tutorial: Using an Amazon S3 trigger to invoke a Lambda function](with-s3-example.md).
+ **Amazon Simple Notification Service (Amazon SNS):** Invokes a function when a message is published to an SNS topic. For more information, see [Tutorial: Using AWS Lambda with Amazon Simple Notification Service](with-sns-example.md).
+ **Amazon API Gateway:** Invokes a function when an API request is made to a specific endpoint. For more information, see [Invoking a Lambda function using an Amazon API Gateway endpoint](services-apigateway.md).

Event source mappings are Lambda resources created and managed within the Lambda service. Event source mappings are designed for processing high-volume streaming data or messages from queues. Processing records from a stream or queue in batches is more efficient than processing records individually. 

## Batching behavior
<a name="invocation-eventsourcemapping-batching"></a>

By default, an event source mapping batches records together into a single payload that Lambda sends to your function. To fine-tune batching behavior, you can configure a batching window ([MaximumBatchingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumBatchingWindowInSeconds)) and a batch size ([BatchSize](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-response-BatchSize)). A batching window is the maximum amount of time to gather records into a single payload. A batch size is the maximum number of records in a single batch. Lambda invokes your function when one of the following three criteria is met:
+ **The batching window reaches its maximum value.** Default batching window behavior varies depending on the specific event source.
  + **For Kinesis, DynamoDB, and Amazon SQS event sources:** The default batching window is 0 seconds. This means that Lambda invokes your function as soon as records are available. To set a batching window, configure `MaximumBatchingWindowInSeconds`. You can set this parameter to any value from 0 to 300 seconds in increments of 1 second. If you configure a batching window, the next window begins as soon as the previous function invocation completes.
  + **For Amazon MSK, self-managed Apache Kafka, Amazon MQ, and Amazon DocumentDB event sources:** The default batching window is 500 ms. You can configure `MaximumBatchingWindowInSeconds` to any value from 0 seconds to 300 seconds in increments of seconds. In provisioned mode for Kafka event source mappings, when you configure a batching window, the next window begins as soon as the previous batch is completed. In non-provisioned Kafka event source mappings, when you configure a batching window, the next window begins as soon as the previous function invocation completes. To minimize latency when using Kafka event source mappings in provisioned mode, set `MaximumBatchingWindowInSeconds` to 0. This setting ensures that Lambda will start processing the next batch immediately after completing the current function invocation. For additional information on low latency processing, see [Low latency Apache Kafka](with-kafka-low-latency.md).
  + **For Amazon MQ and Amazon DocumentDB event sources:** The default batching window is 500 ms. You can configure `MaximumBatchingWindowInSeconds` to any value from 0 seconds to 300 seconds in increments of seconds. A batching window begins as soon as the first record arrives.
**Note**  
Because you can only change `MaximumBatchingWindowInSeconds` in increments of seconds, you cannot revert to the 500 ms default batching window after you have changed it. To restore the default batching window, you must create a new event source mapping.
+ **The batch size is met.** The minimum batch size is 1. The default and maximum batch size depend on the event source. For details about these values, see the [BatchSize](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-BatchSize) specification for the `CreateEventSourceMapping` API operation.
+ **The payload size reaches [6 MB](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html).** You cannot modify this limit.

The following diagram illustrates these three conditions. Suppose a batching window begins at `t = 7` seconds. In the first scenario, the batching window reaches its 40 second maximum at `t = 47` seconds after accumulating 5 records. In the second scenario, the batch size reaches 10 before the batching window expires, so the batching window ends early. In the third scenario, the maximum payload size is reached before the batching window expires, so the batching window ends early.

![\[\]](http://docs.aws.amazon.com/lambda/latest/dg/images/batching-window.png)


We recommend that you test with different batch and record sizes so that the polling frequency of each event source is tuned to how quickly your function is able to complete its task. The [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) `BatchSize` parameter controls the maximum number of records that can be sent to your function with each invoke. A larger batch size can often more efficiently absorb the invoke overhead across a larger set of records, increasing your throughput.

Lambda doesn't wait for any configured [extensions](lambda-extensions.md) to complete before sending the next batch for processing. In other words, your extensions may continue to run as Lambda processes the next batch of records. This can cause throttling issues if you breach any of your account's [concurrency](lambda-concurrency.md) settings or limits. To detect whether this is a potential issue, monitor your functions and check whether you're seeing higher [concurrency metrics](monitoring-concurrency.md#general-concurrency-metrics) than expected for your event source mapping. Due to short times in between invokes, Lambda may briefly report higher concurrency usage than the number of shards. This can be true even for Lambda functions without extensions.

By default, if your function returns an error, the event source mapping reprocesses the entire batch until the function succeeds, or the items in the batch expire. To ensure in-order processing, the event source mapping pauses processing for the affected shard until the error is resolved. For stream sources (DynamoDB and Kinesis), you can configure the maximum number of times that Lambda retries when your function returns an error. Service errors or throttles where the batch does not reach your function do not count toward retry attempts. You can also configure the event source mapping to send an invocation record to a [destination](invocation-async-retain-records.md#invocation-async-destinations) when it discards an event batch.

## Provisioned mode
<a name="invocation-eventsourcemapping-provisioned-mode"></a>

Lambda event source mappings use event pollers to poll your event source for new messages. By default, Lambda manages the autoscaling of these pollers based on message volume. When message traffic increases, Lambda automatically increases the number of event pollers to handle the load, and reduces them when traffic decreases.

In provisioned mode, you can fine-tune the throughput of your event source mapping by defining minimum and maximum limits for dedicated polling resources that remain ready to handle expected traffic patterns. These resources auto-scale 3 times faster to handle sudden spikes in event traffic and provide 16 times higher capacity to process millions of events. This helps you build highly responsive event-driven workloads with stringent performance requirements.

In Lambda, an event poller is a compute unit with throughput capabilities that vary by event source type. For Amazon MSK and self-managed Apache Kafka, each event poller can handle up to 5 MB/sec of throughput or up to 5 concurrent invocations. For example, if your event source produces an average payload of 1 MB and the average duration of your function is 1 second, a single Kafka event poller can support 5 MB/sec throughput and 5 concurrent Lambda invocations (assuming no payload transformation). For Amazon SQS, each event poller can handle up to 1 MB/sec of throughput or up to 10 concurrent invocations. Using provisioned mode incurs additional costs based on your event poller usage. For pricing details, see [AWS Lambda pricing](https://aws.amazon.com/lambda/pricing/).

Provisioned mode is available for Amazon MSK, self-managed Apache Kafka, and Amazon SQS event sources. While concurrency settings give you control over the scaling of your function, provisioned mode gives you control over the throughput of your event source mapping. To ensure maximum performance, you might need to adjust both settings independently.

Provisioned mode is ideal for real-time applications requiring consistent event processing latency, such as financial services firms processing market data feeds, e-commerce platforms providing real-time personalized recommendations, and gaming companies managing live player interactions.

Each event poller supports different throughput capacity:
+ For Amazon MSK and self-managed Apache Kafka: up to 5 MB/sec of throughput or up to 5 concurrent invokes
+ For Amazon SQS: up to 1 MB/sec of throughput or up to 10 concurrent invokes or up to 10 SQS polling API calls per second.

For Amazon SQS event source mappings, you can set the minimum number of pollers between 2 and 200 with a default of 2, and the maximum number between 2 and 2,000 with a default of 200. Lambda scales the number of event pollers between your configured minimum and maximum, quickly adding up to 1,000 concurrency per minute to provide consistent, low-latency processing of your events.

For Kafka event source mappings, you can set the minimum number of pollers between 1 and 200 with a default of 1, and the maximum number between 1 and 2,000 with a default of 200. Lambda scales the number of event pollers between your configured minimum and maximum based on your event backlog in your topic to provide low-latency processing of your events.

Note that for Amazon SQS event sources, the maximum concurrency setting cannot be used with provisioned mode. When using provisioned mode, you control concurrency through the maximum event pollers setting.

For details about configuring provisioned mode, see the following sections:
+ [Configuring provisioned mode for Amazon MSK event source mappings](kafka-scaling-modes.md)
+ [Configuring provisioned mode for self-managed Apache Kafka event source mappings](kafka-scaling-modes.md#kafka-provisioned-mode)
+ [Using provisioned mode with Amazon SQS event source mappings](with-sqs.md#sqs-provisioned-mode)

To minimize latency in provisioned mode, set `MaximumBatchingWindowInSeconds` to 0. This setting ensures that Lambda will start processing the next batch immediately after completing the current function invocation. For additional information on low latency processing, see [Low latency Apache Kafka](with-kafka-low-latency.md).

After configuring provisioned mode, you can observe the usage of event pollers for your workload by monitoring the `ProvisionedPollers` metric. For more information, see [Event source mapping metrics](monitoring-metrics-types.md#event-source-mapping-metrics).

## Event source mapping API
<a name="event-source-mapping-api"></a>

To manage an event source with the [AWS Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) or an [AWS SDK](https://aws.amazon.com/getting-started/tools-sdks/), you can use the following API operations:
+ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)
+ [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html)
+ [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html)
+ [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)
+ [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html)

# Using tags on event source mappings
<a name="tags-esm"></a>

You can tag event source mappings to organize and manage your resources. Tags are free-form key-value pairs associated with your resources that are supported across AWS services. For more information about use cases for tags, see [Common tagging strategies](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#tag-strategies) in the *Tagging AWS Resources and Tag Editor Guide*. 

Event source mappings are associated with functions, which can have their own tags. Event source mappings do not automatically inherit tags from functions. You can use the AWS Lambda API to view and update tags. You can also view and update tags while managing a specific event source mapping in the Lambda console, including those using Provisioned Mode for Amazon SQS.

## Permissions required for working with tags
<a name="esm-tags-required-permissions"></a>

To allow an AWS Identity and Access Management (IAM) identity (user, group, or role) to read or set tags on a resource, grant it the corresponding permissions:
+ **lambda:ListTags**–When a resource has tags, grant this permission to anyone who needs to call `ListTags` on it. For tagged functions, this permission is also necessary for `GetFunction`.
+ **lambda:TagResource**–Grant this permission to anyone who needs to call `TagResource` or perform a tag on create.

Optionally, consider granting the **lambda:UntagResource** permission as well to allow `UntagResource` calls to the resource.

For more information, see [Identity-based IAM policies for Lambda](access-control-identity-based.md).

## Using tags with the Lambda console
<a name="tags-esm-console"></a>

You can use the Lambda console to create event source mappings that have tags, add tags to existing event source mappings, and filter event source mappings by tag, including those configured in Provisioned Mode for Amazon SQS.

When you add a trigger for supported stream and queue-based services using the Lambda console, Lambda automatically creates an event source mapping. For more information about these event sources, see [How Lambda processes records from stream and queue-based event sources](invocation-eventsourcemapping.md). To create an event source mapping in the console, you will need the following prerequisites:
+ A function.
+ An event source from an affected service.

You can add the tags as part of the same user interface you use to create or update triggers.

**To add a tag when you create a event source mapping**

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

1. Choose the name of your function.

1. Under **Function overview**, choose **Add trigger**.

1. Under **Trigger configuration**, in the dropdown list, choose the name of the service your event source comes from.

1. Provide the core configuration for your event source. For more information about configuring your event source, consult the section for the related service in [Invoking Lambda with events from other AWS services](lambda-services.md).

1. Under **Event source mapping configuration**, choose **Additional settings**.

1. Under **Tags**, choose **Add new tag**

1. In the **Key** field, enter your tag key. For information about tagging restrictions, see [Tag naming limits and requirements](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#id_tags_naming_best_practices) in the *Tagging AWS Resources and Tag Editor Guide*.

1. Choose **Add**.

**To add tags to an existing event source mapping**

1. Open [Event source mappings](https://console.aws.amazon.com/lambda/home#/event-source-mappings) in the Lambda console.

1. From the resource list, choose the **UUID** for the event source mapping corresponding to your **Function** and **Event source ARN**.

1. From the tab list below the **General configuration pane**, choose **Tags**.

1. Choose **Manage tags**.

1. Choose **Add new tag**.

1. In the **Key** field, enter your tag key. For information about tagging restrictions, see [Tag naming limits and requirements](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#id_tags_naming_best_practices) in the *Tagging AWS Resources and Tag Editor Guide*.

1. Choose **Save**.

**To filter event source mappings by tag**

1. Open [Event source mappings](https://console.aws.amazon.com/lambda/home#/event-source-mappings) in the Lambda console.

1. Choose the search box.

1. From the dropdown list, select your tag key from below the **Tags** subheading.

1. Select **Use: "tag-name"** to see all event source mappings tagged with this key, or choose an **Operator** to further filter by value.

1. Select your tag value to filter by a combination of tag key and value.

The search box also supports searching for tag keys. Enter the name of a key to find it in the list.

## Using tags with the AWS CLI
<a name="tags-esm-cli"></a>

You can add and remove tags on existing Lambda resources, including event source mappings, with the Lambda API. You can also add tags when creating an event source mapping, which allows you to keep a resource tagged through its entire lifecycle.

### Updating tags with the Lambda tag APIs
<a name="tags-esm-api-config"></a>

You can add and remove tags for supported Lambda resources through the [TagResource](https://docs.aws.amazon.com/lambda/latest/api/API_TagResource.html) and [UntagResource](https://docs.aws.amazon.com/lambda/latest/api/API_UntagResource.html) API operations.

You can call these operations using the AWS CLI. To add tags to an existing resource, use the `tag-resource` command. This example adds two tags, one with the key *Department* and one with the key *CostCenter*.

```
aws lambda tag-resource \
--resource arn:aws:lambda:us-east-2:123456789012:resource-type:my-resource \
--tags Department=Marketing,CostCenter=1234ABCD
```

To remove tags, use the `untag-resource` command. This example removes the tag with the key *Department*.

```
aws lambda untag-resource --resource arn:aws:lambda:us-east-1:123456789012:resource-type:resource-identifier \
--tag-keys Department
```

### Adding tags when you create an event source mapping
<a name="tags-esm-on-create"></a>

To create a new Lambda event source mapping with tags, use the [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) API operation. Specify the `Tags` parameter. You can call this operation with the `create-event-source-mapping` AWS CLI command and the `--tags` option. For more information about the CLI command, see [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) in the *AWS CLI Command Reference*.

Before using the `Tags` parameter with `CreateEventSourceMapping`, ensure that your role has permission to tag resources alongside the usual permissions needed for this operation. For more information about permissions for tagging, see [Permissions required for working with tags](#esm-tags-required-permissions).

### Viewing tags with the Lambda tag APIs
<a name="tags-esm-api-view"></a>

To view the tags that are applied to a specific Lambda resource, use the `ListTags` API operation. For more information, see [ListTags](https://docs.aws.amazon.com/lambda/latest/api/API_ListTags.html).

You can call this operation with the `list-tags` AWS CLI command by providing an ARN (Amazon Resource Name).

```
aws lambda list-tags --resource arn:aws:lambda:us-east-1:123456789012:resource-type:resource-identifier
```

### Filtering resources by tag
<a name="tags-esm-filtering"></a>

You can use the AWS Resource Groups Tagging API [GetResources](https://docs.aws.amazon.com/resourcegroupstagging/latest/APIReference/API_GetResources.html) API operation to filter your resources by tags. The `GetResources` operation receives up to 10 filters, with each filter containing a tag key and up to 10 tag values. You provide `GetResources` with a `ResourceType` to filter by specific resource types.

You can call this operation using the `get-resources` AWS CLI command. For examples of using `get-resources`, see [get-resources](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/resourcegroupstaggingapi/get-resources.html#examples) in the *AWS CLI Command Reference*. 

# Control which events Lambda sends to your function
<a name="invocation-eventfiltering"></a>

You can use event filtering to control which records from a stream or queue Lambda sends to your function. For example, you can add a filter so that your function only processes Amazon SQS messages containing certain data parameters. Event filtering works only with certain event source mappings. You can add filters to event source mappings for the following AWS services:
+ Amazon DynamoDB
+ Amazon Kinesis Data Streams
+ Amazon MQ
+ Amazon Managed Streaming for Apache Kafka (Amazon MSK)
+ Self-managed Apache Kafka
+ Amazon Simple Queue Service (Amazon SQS)

For specific information about filtering with specific event sources, see [Using filters with different AWS services](#filtering-by-service). Lambda doesn't support event filtering for Amazon DocumentDB.

By default, you can define up to five different filters for a single event source mapping. Your filters are logically ORed together. If a record from your event source satisfies one or more of your filters, Lambda includes the record in the next event it sends to your function. If none of your filters are satisfied, Lambda discards the record.

**Note**  
If you need to define more than five filters for an event source, you can request a quota increase for up to 10 filters for each event source. If you attempt to add more filters than your current quota permits, Lambda will return an error when you try to create the event source.

**Topics**
+ [

## Understanding event filtering basics
](#filtering-basics)
+ [

## Handling records that don't meet filter criteria
](#filtering-criteria-not-met)
+ [

## Filter rule syntax
](#filtering-syntax)
+ [

## Attaching filter criteria to an event source mapping (console)
](#filtering-console)
+ [

## Attaching filter criteria to an event source mapping (AWS CLI)
](#filtering-cli)
+ [

## Attaching filter criteria to an event source mapping (AWS SAM)
](#filtering-sam)
+ [

## Encryption of filter criteria
](#filter-criteria-encryption)
+ [

## Using filters with different AWS services
](#filtering-by-service)

## Understanding event filtering basics
<a name="filtering-basics"></a>

A filter criteria (`FilterCriteria`) object is a structure that consists of a list of filters (`Filters`). Each filter is a structure that defines an event filtering pattern (`Pattern`). A pattern is a string representation of a JSON filter rule. The structure of a `FilterCriteria` object is as follows.

```
{
   "Filters": [
        {
            "Pattern": "{ \"Metadata1\": [ rule1 ], \"data\": { \"Data1\": [ rule2 ] }}"
        }
    ]
}
```

For added clarity, here is the value of the filter's `Pattern` expanded in plain JSON.

```
{
    "Metadata1": [ rule1 ],
    "data": {
        "Data1": [ rule2 ]
    }
}
```

Your filter pattern can include metadata properties, data properties, or both. The available metadata parameters and the format of the data parameters vary according to the AWS service which is acting as the event source. For example, suppose your event source mapping receives the following record from an Amazon SQS queue:

```
{
    "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
    "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
    "body": "{\\n \"City\": \"Seattle\",\\n \"State\": \"WA\",\\n \"Temperature\": \"46\"\\n}",
    "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1545082649183",
        "SenderId": "AIDAIENQZJOLO23YVJ4VO",
        "ApproximateFirstReceiveTimestamp": "1545082649185"
    },
    "messageAttributes": {},
    "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
    "eventSource": "aws:sqs",
    "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
    "awsRegion": "us-east-2"
}
```
+ **Metadata properties** are the fields containing information about the event that created the record. In the example Amazon SQS record, the metadata properties include fields such as `messageID`, `eventSourceArn`, and `awsRegion`.
+ **Data properties** are the fields of the record containing the data from your stream or queue. In the Amazon SQS event example, the key for the data field is `body`, and the data properties are the fields `City` `State`, and `Temperature`.

Different types of event source use different key values for their data fields. To filter on data properties, make sure that you use the correct key in your filter’s pattern. For a list of data filtering keys, and to see examples of filter patterns for each supported AWS service, refer to [Using filters with different AWS services](#filtering-by-service).

Event filtering can handle multi-level JSON filtering. For example, consider the following fragment of a record from a DynamoDB stream:

```
"dynamodb": {
    "Keys": {
        "ID": {
            "S": "ABCD"
        }
        "Number": {
            "N": "1234"
    },
    ...
}
```

Suppose you want to process only those records where the value of the sort key `Number` is 4567. In this case, your `FilterCriteria` object would look like this:

```
{
    "Filters": [
        {
            "Pattern": "{ \"dynamodb\": { \"Keys\": { \"Number\": { \"N\": [ "4567" ] } } } }"
        }
    ]
}
```

For added clarity, here is the value of the filter's `Pattern` expanded in plain JSON. 

```
{
    "dynamodb": {
        "Keys": {
            "Number": {
                "N": [ "4567" ]
                }
            }
        }
}
```

## Handling records that don't meet filter criteria
<a name="filtering-criteria-not-met"></a>

How Lambda handles records that don't meet your filter criteria depends on the event source.
+ For **Amazon SQS**, if a message doesn't satisfy your filter criteria, Lambda automatically removes the message from the queue. You don't have to manually delete these messages in Amazon SQS.
+ For **Kinesis** and **DynamoDB**, after your filter criteria evaluates a record, the streams iterator advances past this record. If the record doesn't satisfy your filter criteria, you don't have to manually delete the record from your event source. After the retention period, Kinesis and DynamoDB automatically delete these old records. If you want records to be deleted sooner, see [Changing the Data Retention Period](https://docs.aws.amazon.com/streams/latest/dev/kinesis-extended-retention.html).
+ For **Amazon MSK**, **self-managed Apache Kafka**, and **Amazon MQ** messages, Lambda drops messages that don't match all fields included in the filter. For Amazon MSK and self-managed Apache Kafka, Lambda commits offsets for matched and unmatched messages after successfully invoking the function. For Amazon MQ, Lambda acknowledges matched messages after successfully invoking the function, and acknowledges unmatched messages when filtering them.

## Filter rule syntax
<a name="filtering-syntax"></a>

For filter rules, Lambda supports the Amazon EventBridge rules and uses the same syntax as EventBridge. For more information, see [ Amazon EventBridge event patterns](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html) in the *Amazon EventBridge User Guide*.

The following is a summary of all the comparison operators available for Lambda event filtering.


| Comparison operator | Example | Rule syntax | 
| --- | --- | --- | 
|  Null  |  UserID is null  |  "UserID": [ null ]  | 
|  Empty  |  LastName is empty  |  "LastName": [""]  | 
|  Equals  |  Name is "Alice"  |  "Name": [ "Alice" ]  | 
|  Equals (ignore case)  |  Name is "Alice"  |  "Name": [ \$1 "equals-ignore-case": "alice" \$1 ]  | 
|  And  |  Location is "New York" and Day is "Monday"  |  "Location": [ "New York" ], "Day": ["Monday"]  | 
|  Or  |  PaymentType is "Credit" or "Debit"  |  "PaymentType": [ "Credit", "Debit"]  | 
|  Or (multiple fields)  |  Location is "New York", or Day is "Monday".  |  "\$1or": [ \$1 "Location": [ "New York" ] \$1, \$1 "Day": [ "Monday" ] \$1 ]   | 
|  Not  |  Weather is anything but "Raining"  |  "Weather": [ \$1 "anything-but": [ "Raining" ] \$1 ]  | 
|  Numeric (equals)  |  Price is 100  |  "Price": [ \$1 "numeric": [ "=", 100 ] \$1 ]  | 
|  Numeric (range)  |  Price is more than 10, and less than or equal to 20  |  "Price": [ \$1 "numeric": [ ">", 10, "<=", 20 ] \$1 ]  | 
|  Exists  |  ProductName exists  |  "ProductName": [ \$1 "exists": true \$1 ]  | 
|  Does not exist  |  ProductName does not exist  |  "ProductName": [ \$1 "exists": false \$1 ]  | 
|  Begins with  |  Region is in the US  |  "Region": [ \$1"prefix": "us-" \$1 ]  | 
|  Ends with  |  FileName ends with a .png extension.  |  "FileName": [ \$1 "suffix": ".png" \$1 ]   | 

**Note**  
Like EventBridge, for strings, Lambda uses exact character-by-character matching without case-folding or any other string normalization. For numbers, Lambda also uses string representation. For example, 300, 300.0, and 3.0e2 are not considered equal.

Note that the Exists operator only works on leaf nodes in your event source JSON. It doesn't match intermediate nodes. For example, with the following JSON, the filter pattern `{ "person": { "address": [ { "exists": true } ] } }"` wouldn't find a match because `"address"` is an intermediate node.

```
{
  "person": {
    "name": "John Doe",
    "age": 30,
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "country": "USA"
    }
  }
}
```

## Attaching filter criteria to an event source mapping (console)
<a name="filtering-console"></a>

Follow these steps to create a new event source mapping with filter criteria using the Lambda console.

**To create a new event source mapping with filter criteria (console)**

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

1. Choose the name of a function to create an event source mapping for.

1. Under **Function overview**, choose **Add trigger**.

1. For **Trigger configuration**, choose a trigger type that supports event filtering. For a list of supported services, refer to the list at the beginning of this page.

1. Expand **Additional settings**.

1. Under **Filter criteria**, choose **Add**, and then define and enter your filters. For example, you can enter the following.

   ```
   { "Metadata" : [ 1, 2 ] }
   ```

   This instructs Lambda to process only the records where field `Metadata` is equal to 1 or 2. You can continue to select **Add** to add more filters up to the maximum allowed amount.

1. When you have finished adding your filters, choose **Save**.

When you enter filter criteria using the console, you enter only the filter pattern and don't need to provide the `Pattern` key or escape quotes. In step 6 of the preceding instructions, `{ "Metadata" : [ 1, 2 ] }` corresponds to the following `FilterCriteria`.

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

After creating your event source mapping in the console, you can see the formatted `FilterCriteria` in the trigger details. For more examples of creating event filters using the console, see [Using filters with different AWS services](#filtering-by-service).

## Attaching filter criteria to an event source mapping (AWS CLI)
<a name="filtering-cli"></a>

Suppose you want an event source mapping to have the following `FilterCriteria`:

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

To create a new event source mapping with these filter criteria using the AWS Command Line Interface (AWS CLI), run the following command.

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"Metadata\" : [ 1, 2 ]}"}]}'
```

This [ create-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-event-source-mapping.html) command creates a new Amazon SQS event source mapping for function `my-function` with the specified `FilterCriteria`.

To add these filter criteria to an existing event source mapping, run the following command.

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"Metadata\" : [ 1, 2 ]}"}]}'
```

Note that to update an event source mapping, you need its UUID. You can get the UUID from a [ list-event-source-mappings](https://docs.aws.amazon.com/cli/latest/reference/lambda/list-event-source-mappings.html) call. Lambda also returns the UUID in the [ create-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-event-source-mapping.html) CLI response.

To remove filter criteria from an event source, you can run the following [ update-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/update-event-source-mapping.html) command with an empty `FilterCriteria` object.

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria "{}"
```

For more examples of creating event filters using the AWS CLI, see [Using filters with different AWS services](#filtering-by-service).

## Attaching filter criteria to an event source mapping (AWS SAM)
<a name="filtering-sam"></a>

 Suppose you want to configure an event source in AWS SAM to use the following filter criteria: 

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

 To add these filter criteria to your event source mapping, insert the following snippet into the YAML template for your event source.

```
FilterCriteria: 
  Filters: 
    - Pattern: '{"Metadata": [1, 2]}'
```

 For more information on creating and configuring an AWS SAM template for an event source mapping, see the [ EventSource](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html) section of the AWS SAM Developer Guide. Fore more examples of creating event filters using AWS SAM templates, see [Using filters with different AWS services](#filtering-by-service). 

## Encryption of filter criteria
<a name="filter-criteria-encryption"></a>

By default, Lambda doesn't encrypt your filter criteria object. For use cases where you may include sensitive information in your filter criteria object, you can use your own [KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys) to encrypt it.

After you encrypt your filter criteria object, you can view its plaintext version using a [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API call. You must have `kms:Decrypt` permissions to be able to successfully view the filter criteria in plaintext.

**Note**  
If your filter criteria object is encrypted, Lambda redacts the value of the `FilterCriteria` field in the response of [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html) calls. Instead, this field displays as `null`. To see the true value of `FilterCriteria`, use the [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API.  
To view the decrypted value of `FilterCriteria` in the console, ensure that your IAM role contains permissions for [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html).

You can specify your own KMS key via the console, API/CLI, or CloudFormation.

**To encrypt filter criteria with a customer-owned KMS key (console)**

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

1. Choose **Add trigger**. If you already have an existing trigger, choose the **Configuration** tab, and then choose ** Triggers**. Select the existing trigger, and choose **Edit**.

1. Select the checkbox next to **Encrypt with customer managed KMS key**.

1. For **Choose a customer managed KMS encryption key**, select an existing enabled key or create a new key. Depending on the operation, you need some or all of the following permissions: `kms:DescribeKey`, `kms:GenerateDataKey`, and `kms:Decrypt`. Use the KMS key policy to grant these permissions.

If you use your own KMS key, the following API operations must be permitted in the [key policy](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html):
+ `kms:Decrypt` – Must be granted to the regional Lambda service principal (`lambda.AWS_region.amazonaws.com`). This allows Lambda to decrypt data with this KMS key.
  + To prevent a [ cross-service confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html), the key policy uses the [https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn) global condition key. The correct value of the `aws:SourceArn` key is the ARN of your event source mapping resource, so you can add this to your policy only after you know its ARN. Lambda also forwards the `aws:lambda:FunctionArn` and `aws:lambda:EventSourceArn` keys and their respective values in the [encryption context](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context) when making a decryption request to KMS. These values must match the specified conditions in the key policy for the decryption request to succeed. You don't need to include EventSourceArn for Self-managed Kafka event sources since they don't have an EventSourceArn.
+ `kms:Decrypt` – Must also be granted to the principal that intends to use the key to view the plaintext filter criteria in [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) or [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API calls.
+ `kms:DescribeKey` – Provides the customer managed key details to allow the specified principal to use the key.
+ `kms:GenerateDataKey` – Provides permissions for Lambda to generate a data key to encrypt the filter criteria, on behalf of the specified principal ([envelope encryption](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#enveloping)).

You can use AWS CloudTrail to track AWS KMS requests that Lambda makes on your behalf. For sample CloudTrail events, see [Monitoring your encryption keys for Lambda](security-encryption-at-rest.md#encryption-key-monitoring).

We also recommend using the [https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-via-service](https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-via-service) condition key to limit the use of the KMS key to requests from Lambda only. The value of this key is the regional Lambda service principal (`lambda.AWS_region.amazonaws.com`). The following is a sample key policy that grants all the relevant permissions:

**Example AWS KMS key policy**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Id": "example-key-policy-1",
    "Statement": [
        {
            "Sid": "Allow Lambda to decrypt using the key",
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.us-east-1.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "*",
            "Condition": {
                "ArnEquals" : {
                    "aws:SourceArn": [
                        "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:<esm_uuid>"
                    ]
                },
                "StringEquals": {
                    "kms:EncryptionContext:aws:lambda:FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:test-function",
                    "kms:EncryptionContext:aws:lambda:EventSourceArn": "arn:aws:sqs:us-east-1:123456789012:test-queue"
                }
            }
        },
        {
            "Sid": "Allow actions by an AWS account on the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key to specific roles",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/ExampleRole"
            },
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:GenerateDataKey"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals" : {
                    "kms:ViaService": "lambda.us-east-1.amazonaws.com"
                }
            }
        }
    ]
}
```

To use your own KMS key to encrypt filter criteria, you can also use the following [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) AWS CLI command. Specify the KMS key ARN with the `--kms-key-arn` flag.

```
aws lambda create-event-source-mapping --function-name my-function \
    --maximum-batching-window-in-seconds 60 \
    --event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
    --filter-criteria "{\"filters\": [{\"pattern\": \"{\"a\": [\"1\", \"2\"]}\" }]}" \
    --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599
```

If you have an existing event source mapping, use the [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) AWS CLI command instead. Specify the KMS key ARN with the `--kms-key-arn` flag.

```
aws lambda update-event-source-mapping --function-name my-function \
    --maximum-batching-window-in-seconds 60 \
    --event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
    --filter-criteria "{\"filters\": [{\"pattern\": \"{\"a\": [\"1\", \"2\"]}\" }]}" \
    --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599
```

This operation overwrites any KMS key that was previously specified. If you specify the `--kms-key-arn` flag along with an empty argument, Lambda stops using your KMS key to encrypt filter criteria. Instead, Lambda defaults back to using an Amazon-owned key.

To specify your own KMS key in a CloudFormation template, use the `KMSKeyArn` property of the `AWS::Lambda::EventSourceMapping` resource type. For example, you can insert the following snippet into the YAML template for your event source.

```
MyEventSourceMapping:
  Type: AWS::Lambda::EventSourceMapping
  Properties:
    ...
    FilterCriteria:
      Filters:
        - Pattern: '{"a": [1, 2]}'
    KMSKeyArn: "arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599"
    ...
```

To be able to view your encrypted filter criteria in plaintext in a [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) or [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API call, you must have `kms:Decrypt` permissions.

Starting August 6, 2024, the `FilterCriteria` field no longer shows up in AWS CloudTrail logs from [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html), [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html), and [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API calls if your function doesn't use event filtering. If your function does use event filtering, the `FilterCriteria` field shows up as empty (`{}`). You can still view your filter criteria in plaintext in the response of [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API calls if you have `kms:Decrypt` permissions for the correct KMS key.

### Sample CloudTrail log entry for Create/Update/DeleteEventSourceMapping calls
<a name="filter-criteria-encryption-cloudtrail"></a>

In the following AWS CloudTrail sample log entry for a CreateEventSourceMapping call, `FilterCriteria` shows up as empty (`{}`) because the function uses event filtering. This is the case even if `FilterCriteria` object contains valid filter criteria that your function is actively using. If the function doesn't use event filtering, CloudTrail won't display the `FilterCriteria` field at all in log entries.

```
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROA123456789EXAMPLE:userid1",
        "arn": "arn:aws:sts::123456789012:assumed-role/Example/example-role",
        "accountId": "123456789012",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROA987654321EXAMPLE",
                "arn": "arn:aws:iam::123456789012:role/User1",
                "accountId": "123456789012",
                "userName": "User1"
            },
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2024-05-09T20:35:01Z",
                "mfaAuthenticated": "false"
            }
        },
        "invokedBy": "AWS Internal"
    },
    "eventTime": "2024-05-09T21:05:41Z",
    "eventSource": "lambda.amazonaws.com",
    "eventName": "CreateEventSourceMapping20150331",
    "awsRegion": "us-east-2",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "requestParameters": {
        "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:example-queue",
        "functionName": "example-function",
        "enabled": true,
        "batchSize": 10,
        "filterCriteria": {},
        "kMSKeyArn": "arn:aws:kms:us-east-2:123456789012:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "scalingConfig": {},
        "maximumBatchingWindowInSeconds": 0,
        "sourceAccessConfigurations": []
    },
    "responseElements": {
        "uUID": "a1b2c3d4-5678-90ab-cdef-EXAMPLEaaaaa",
        "batchSize": 10,
        "maximumBatchingWindowInSeconds": 0,
        "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:example-queue",
        "filterCriteria": {},
        "kMSKeyArn": "arn:aws:kms:us-east-2:123456789012:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:example-function",
        "lastModified": "May 9, 2024, 9:05:41 PM",
        "state": "Creating",
        "stateTransitionReason": "USER_INITIATED",
        "functionResponseTypes": [],
        "eventSourceMappingArn": "arn:aws:lambda:us-east-2:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLEbbbbb"
    },
    "requestID": "a1b2c3d4-5678-90ab-cdef-EXAMPLE33333",
    "eventID": "a1b2c3d4-5678-90ab-cdef-EXAMPLE22222",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "sessionCredentialFromConsole": "true"
}
```

## Using filters with different AWS services
<a name="filtering-by-service"></a>

Different types of event source use different key values for their data fields. To filter on data properties, make sure that you use the correct key in your filter’s pattern. The following table gives the filtering keys for each supported AWS service.


| AWS service | Filtering key | 
| --- | --- | 
| DynamoDB | dynamodb | 
| Kinesis | data | 
| Amazon MQ | data | 
| Amazon MSK | value | 
| Self-managed Apache Kafka | value | 
| Amazon SQS | body | 

The following sections give examples of filter patterns for different types of event sources. They also provide definitions of supported incoming data formats and filter pattern body formats for each supported service.
+ [Using event filtering with a DynamoDB event source](with-ddb-filtering.md)
+ [Using event filtering with a Kinesis event source](with-kinesis-filtering.md)
+ [Filter events from an Amazon MQ event source](with-mq-filtering.md)
+ [Filtering events from Amazon MSK and self-managed Apache Kafka event sources](kafka-filtering.md)
+ [Using event filtering with an Amazon SQS event source](with-sqs-filtering.md)

# Testing Lambda functions in the console
<a name="testing-functions"></a>

You can test your Lambda function in the console by invoking your function with a test event. A *test event* is a JSON input to your function. If your function doesn't require input, the event can be an empty document `({})`.

When you run a test in the console, Lambda synchronously invokes your function with the test event. The function runtime converts the event JSON into an object and passes it to your code's handler method for processing.

**Create a test event**  
Before you can test in the console, you need to create a private or shareable test event.

## Invoking functions with test events
<a name="invoke-with-event"></a>

**To test a function**

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 test.

1. Choose the **Test** tab.

1. Under **Test event**, choose **Create new event** or **Edit saved event** and then choose the saved event that you want to use.

1. Optionally - choose a **Template** for the event JSON.

1. Choose **Test**.

1. To review the test results, under **Execution result**, expand **Details**.

To invoke your function without saving your test event, choose **Test** before saving. This creates an unsaved test event that Lambda preserves only for the duration of the session.

For the Node.js, Python, and Ruby runtimes, you can also access your existing saved and unsaved test events on the **Code** tab. Use the **TEST EVENTS** section to create, edit, and run tests.

## Creating private test events
<a name="creating-private-events"></a>

Private test events are available only to the event creator, and they require no additional permissions to use. You can create and save up to 10 private test events per function.

**To create a private test event**

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 test.

1. Choose the **Test** tab.

1. Under **Test event**, do the following:

   1. Choose a **Template**.

   1. Enter a **Name** for the test.

   1. In the text entry box, enter the JSON test event.

   1. Under **Event sharing settings**, choose **Private**.

1. Choose **Save changes**.

For the Node.js, Python, and Ruby runtimes, you can also create test events on the **Code** tab. Use the **TEST EVENTS** section to create, edit, and run tests.

## Creating shareable test events
<a name="creating-shareable-events"></a>

Shareable test events are test events that you can share with other users in the same AWS account. You can edit other users' shareable test events and invoke your function with them.

Lambda saves shareable test events as schemas in an [Amazon EventBridge (CloudWatch Events) schema registry](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-schema-registry.html) named `lambda-testevent-schemas`. As Lambda utilizes this registry to store and call shareable test events you create, we recommend that you do not edit this registry or create a registry using the `lambda-testevent-schemas` name.

To see, share, and edit shareable test events, you must have permissions for all of the following [EventBridge (CloudWatch Events) schema registry API operations](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/operations.html):
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#CreateRegistry](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#CreateRegistry)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#CreateSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#CreateSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DeleteSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DeleteSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-version-schemaversion.html#DeleteSchemaVersion](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-version-schemaversion.html#DeleteSchemaVersion)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#DescribeRegistry](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#DescribeRegistry)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DescribeSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DescribeSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-discover.html#GetDiscoveredSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-discover.html#GetDiscoveredSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-versions.html#ListSchemaVersions](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-versions.html#ListSchemaVersions)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#UpdateSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#UpdateSchema)

Note that saving edits made to a shareable test event overwrites that event.

If you cannot create, edit, or see shareable test events, check that your account has the required permissions for these operations. If you have the required permissions but still cannot access shareable test events, check for any [resource-based policies](access-control-resource-based.md) that might limit access to the EventBridge (CloudWatch Events) registry.

**To create a shareable test event**

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 test.

1. Choose the **Test** tab.

1. Under **Test event**, do the following:

   1. Choose a **Template**.

   1. Enter a **Name** for the test.

   1. In the text entry box, enter the JSON test event.

   1. Under **Event sharing settings**, choose **Shareable**.

1. Choose **Save changes**.

**Use shareable test events with AWS Serverless Application Model.**  
You can use AWS SAM to invoke shareable test events. See [https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html](https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html) in the [AWS Serverless Application Model Developer Guide](https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html)

## Deleting shareable test event schemas
<a name="deleting-test-schemas"></a>

When you delete shareable test events, Lambda removes them from the `lambda-testevent-schemas` registry. If you remove the last shareable test event from the registry, Lambda deletes the registry.

If you delete the function, Lambda does not delete any associated shareable test event schemas. You must clean up these resources manually from the [EventBridge (CloudWatch Events) console](https://console.aws.amazon.com/events).

# Lambda function states
<a name="functions-states"></a>

Lambda includes a [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) field in the function configuration for all functions to indicate when your function is ready to invoke. `State` provides information about the current status of the function, including whether you can successfully invoke the function. Function states do not change the behavior of function invocations or how your function runs the code.

**Note**  
Function state definitions differ slightly for [SnapStart](snapstart.md) functions. For more information, see [Lambda SnapStart and function states](snapstart-activate.md#snapstart-function-states).

In many cases, a DynamoDB table is an ideal way to retain state between invocations since it provides low-latency data access and can scale with the Lambda service. You can also store data in [ Amazon EFS for Lambda](https://aws.amazon.com/blogs/compute/using-amazon-efs-for-aws-lambda-in-your-serverless-applications/) if you are using this service, and this provides low-latency access to file system storage.

Function states include:
+ `Pending` – After Lambda creates the function, it sets the state to pending. While in pending state, Lambda attempts to create or configure resources for the function, such as VPC or EFS resources. Lambda does not invoke a function during pending state. Any invocations or other API actions that operate on the function will fail.
+ `Active` – Your function transitions to active state after Lambda completes resource configuration and provisioning. Functions can only be successfully invoked while active.
+ `Failed` – Indicates that resource configuration or provisioning encountered an error. When function creation fails, Lambda sets the function state to failed, and you must delete and recreate the function.
+ `Inactive` – A function becomes inactive when it has been idle long enough for Lambda to reclaim the external resources that were configured for it. When you try to invoke a function that is inactive, the invocation fails and Lambda sets the function to pending state until the function resources are recreated. If Lambda fails to recreate the resources, the function returns to the inactive state. You might need to resolve any errors and redeploy your function to restore it to the active state.

If you are using SDK-based automation workflows or calling Lambda’s service APIs directly, ensure that you check a function's state before invocation to verify that it is active. You can do this with the Lambda API action [GetFunction](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunction.html), or by configuring a waiter using the [AWS SDK for Java 2.0](https://github.com/aws/aws-sdk-java-v2).

```
aws lambda get-function --function-name my-function --query 'Configuration.[State, LastUpdateStatus]'
```

You should see the following output:

```
[
 "Active",
 "Successful" 
]
```

The following operations fail while function creation is pending:
+ [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [PublishVersion](https://docs.aws.amazon.com/lambda/latest/api/API_PublishVersion.html)

## Function states during updates
<a name="functions-states-updating"></a>

Lambda has two operations for updating functions:
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html): Updates the function's deployment package
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html): Updates the function's configuration

Lambda uses the [LastUpdateStatus](https://docs.aws.amazon.com/lambda/latest/api/API_FunctionConfiguration.html#lambda-Type-FunctionConfiguration-LastUpdateStatus) attribute to track the progress of these update operations. While an update is in progress (when `"LastUpdateStatus": "InProgress"`):
+ The function's [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) remains `Active`.
+ Invocations continue to use the function's previous code and configuration until the update completes.
+ The following operations fail:
  + [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)
  + [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
  + [PublishVersion](https://docs.aws.amazon.com/lambda/latest/api/API_PublishVersion.html)
  + [TagResource](https://docs.aws.amazon.com/lambda/latest/api/API_TagResource.html)

When an update fails (when `"LastUpdateStatus": "Failed"`):
+ The function's [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) remains `Active`.
+ Invocations continue to use the function's previous code and configuration.

**Example GetFunctionConfiguration response**  
The following example is the result of [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html) request on a function undergoing an update.  

```
{
    "FunctionName": "my-function",
    "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
    "Runtime": "nodejs24.x",
    "VpcConfig": {
        "SubnetIds": [
            "subnet-071f712345678e7c8",
            "subnet-07fd123456788a036",
            "subnet-0804f77612345cacf"
        ],
        "SecurityGroupIds": [
            "sg-085912345678492fb"
        ],
        "VpcId": "vpc-08e1234569e011e83"
    },
    "State": "Active",
    "LastUpdateStatus": "InProgress",
    ...
}
```

# Understanding retry behavior in Lambda
<a name="invocation-retries"></a>

When you invoke a function directly, you determine the strategy for handling errors related to your function code. Lambda does not automatically retry these types of errors on your behalf. To retry, you can manually re-invoke your function, send the failed event to a queue for debugging, or ignore the error. Your function's code might have run completely, partially, or not at all. If you retry, ensure that your function's code can handle the same event multiple times without causing duplicate transactions or other unwanted side effects.

When you invoke a function indirectly, you need to be aware of the retry behavior of the invoker and any service that the request encounters along the way. This includes the following scenarios.
+ **Asynchronous invocation** – Lambda retries function errors twice. If the function doesn't have enough capacity to handle all incoming requests, events might wait in the queue for hours to be sent to the function. You can configure a dead-letter queue on the function to capture events that weren't successfully processed. For more information, see [Adding a dead-letter queue](invocation-async-retain-records.md#invocation-dlq).
+ **Event source mappings** – Event source mappings that read from streams retry the entire batch of items. Repeated errors block processing of the affected shard until the error is resolved or the items expire. To detect stalled shards, you can monitor the [Iterator Age](monitoring-metrics.md) metric.

  For event source mappings that read from a queue, you determine the length of time between retries and destination for failed events by configuring the visibility timeout and redrive policy on the source queue. For more information, see [How Lambda processes records from stream and queue-based event sources](invocation-eventsourcemapping.md) and the service-specific topics under [Invoking Lambda with events from other AWS services](lambda-services.md).
+ **AWS services** – AWS services can invoke your function [synchronously](invocation-sync.md) or asynchronously. For synchronous invocation, the service decides whether to retry. For example, Amazon S3 batch operations retries the operation if the Lambda function returns a `TemporaryFailure` response code. Services that proxy requests from an upstream user or client may have a retry strategy or may relay the error response back to the requester. For example, API Gateway always relays the error response back to the requester. 

  For asynchronous invocation, the retry logic is the same regardless of the invocation source. By default, Lambda retries a failed asynchronous invocation up to two times. For more information, see [How Lambda handles errors and retries with asynchronous invocation](invocation-async-error-handling.md).
+ **Other accounts and clients** – When you grant access to other accounts, you can use [resource-based policies](access-control-resource-based.md) to restrict the services or resources they can configure to invoke your function. To protect your function from being overloaded, consider putting an API layer in front of your function with [Amazon API Gateway](services-apigateway.md).

To help you deal with errors in Lambda applications, Lambda integrates with services like Amazon CloudWatch and AWS X-Ray. You can use a combination of logs, metrics, alarms, and tracing to quickly detect and identify issues in your function code, API, or other resources that support your application. For more information, see [Monitoring, debugging, and troubleshooting Lambda functions](lambda-monitoring.md).

# Use Lambda recursive loop detection to prevent infinite loops
<a name="invocation-recursion"></a>

When you configure a Lambda function to output to the same service or resource that invokes the function, it's possible to create an infinite recursive loop. For example, a Lambda function might write a message to an Amazon Simple Queue Service (Amazon SQS) queue, which then invokes the same function. This invocation causes the function to write another message to the queue, which in turn invokes the function again.

Unintentional recursive loops can result in unexpected charges being billed to your AWS account. Loops can also cause Lambda to [scale](lambda-concurrency.md) and use all of your account's available concurrency. To help reduce the impact of unintentional loops, Lambda detects certain types of recursive loops shortly after they occur. By default, when Lambda detects a recursive loop, it stops your function being invoked and notifies you. If your design intentionally uses recursive patterns, you can a change a function's default configuration to allow it to be invoked recursively. See [Allowing a Lambda function to run in a recursive loop](#invocation-recursion-disable) for more information.

**Topics**
+ [

## Understanding recursive loop detection
](#invocation-recursion-concepts)
+ [

## Supported AWS services and SDKs
](#invocation-recursion-supported)
+ [

## Recursive loop notifications
](#invocation-recursion-monitoring)
+ [

## Responding to recursive loop detection notifications
](#invocation-recursion-responding)
+ [

## Allowing a Lambda function to run in a recursive loop
](#invocation-recursion-disable)
+ [

## Supported Regions for Lambda recursive loop detection
](#invocation-recursion-regions)

## Understanding recursive loop detection
<a name="invocation-recursion-concepts"></a>

Recursive loop detection in Lambda works by tracking events. Lambda is an event-driven compute service that runs your function code when certain events occur. For example, when an item is added to an Amazon SQS queue or Amazon Simple Notification Service (Amazon SNS) topic. Lambda passes events to your function as JSON objects, which contain information about the change in the system state. When an event causes your function to run, this is called an *invocation*.

To detect recursive loops, Lambda uses [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) tracing headers. When [AWS services that support recursive loop detection](#invocation-recursion-supportedservices) send events to Lambda, those events are automatically annotated with metadata. When your Lambda function writes one of these events to another supported AWS service using a [supported version of an AWS SDK](#invocation-recursion-supportedsdks), it updates this metadata. The updated metadata includes a count of the number of times that the event has invoked the function.

**Note**  
You don't need to enable X-Ray active tracing for this feature to work. Recursive loop detection is turned on by default for all AWS customers. There is no charge to use the feature.

A *chain of requests* is a sequence of Lambda invocations caused by the same triggering event. For example, imagine that an Amazon SQS queue invokes your Lambda function. Your Lambda function then sends the processed event back to the same Amazon SQS queue, which invokes your function again. In this example, each invocation of your function falls in the same chain of requests.

If your function is invoked approximately 16 times in the same chain of requests, then Lambda automatically stops the next function invocation in that request chain and notifies you. If your function is configured with multiple triggers, then invocations from other triggers aren't affected.

**Note**  
Even when the `maxReceiveCount` setting on the source queue's redrive policy is higher than 16, Lambda recursion protection does not prevent Amazon SQS from retrying the message after a recursive loop is detected and terminated. When Lambda detects a recursive loop and drops subsequent invocations, it returns a `RecursiveInvocationException` to the event source mapping. This increments the `receiveCount` value on the message. Lambda continues to retry the message, and continues to block function invocations, until Amazon SQS determines that the `maxReceiveCount` is exceeded and sends the message to the configured dead-letter queue.

If you have an [on-failure destination](invocation-async-retain-records.md#invocation-async-destinations) or [dead-letter queue](invocation-async-retain-records.md#invocation-dlq) configured for your function, then Lambda also sends the event from the stopped invocation to your destination or dead-letter queue. When configuring a destination or dead-letter queue for your function, be sure not to use an event trigger or event source mapping that your function also uses. If you send events to the same resource that invokes your function, then you can create another recursive loop and this loop will also be terminated. If you opt out of recursion loop detection, this loop will not be terminated.

## Supported AWS services and SDKs
<a name="invocation-recursion-supported"></a>

Lambda can detect only recursive loops that include certain supported AWS services. For recursive loops to be detected, your function must also use one of the supported AWS SDKs.

### Supported AWS services
<a name="invocation-recursion-supportedservices"></a>

Lambda currently detects recursive loops between your functions, Amazon SQS, Amazon S3, and Amazon SNS. Lambda also detects loops comprised only of Lambda functions, which may invoke each other synchronously or asynchronously. The following diagrams show some examples of loops that Lambda can detect:

![\[Diagrams of recursive loops between a Lambda function, Amazon SNS, Amazon S3, and an Amazon SQS queue.\]](http://docs.aws.amazon.com/lambda/latest/dg/images/RunawayWorkloadDetected_v3.png)


When another AWS service such as Amazon DynamoDB forms part of the loop, Lambda can't currently detect and stop it.

Because Lambda currently detects only recursive loops involving Amazon SQS, Amazon S3, and Amazon SNS, it's still possible that loops involving other AWS services can result in unintended usage of your Lambda functions.

To guard against unexpected charges being billed to your AWS account, we recommend that you configure [Amazon CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) to alert you to unusual usage patterns. For example, you can configure CloudWatch to notify you about spikes in Lambda function concurrency or invocations. You can also configure a [billing alarm](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html) to notify you when spending in your account exceeds a threshold that you specify. Or, you can use [AWS Cost Anomaly Detection](https://docs.aws.amazon.com/cost-management/latest/userguide/manage-ad.html) to alert you to unusual billing patterns.

### Supported AWS SDKs
<a name="invocation-recursion-supportedsdks"></a>

For Lambda to detect recursive loops, your function must use one of the following SDK versions or higher:


| Runtime | Minimum required AWS SDK version | 
| --- | --- | 
|  Node.js  |  2.1147.0 (SDK version 2) 3.105.0 (SDK version 3)  | 
|  Python  |  1.24.46 (boto3) 1.27.46 (botocore)  | 
|  Java 8 and Java 11  |  2.17.135  | 
|  Java 17  |  2.20.81  | 
|  Java 21  |  2.21.24  | 
|  .NET  |  3.7.293.0  | 
|  Ruby  |  3.134.0  | 
|  PHP  |  3.232.0  | 
|  Go  |  V2 SDK 1.57.0  | 

Some Lambda runtimes such as Python and Node.js include a version of the AWS SDK. If the SDK version included in your function's runtime is lower than the minimum required, then you can add a supported version of the SDK to your function's deployment package. You can also add a supported SDK version to your function using a [Lambda layer](chapter-layers.md). For a list of the SDKs included with each Lambda runtime, see [Lambda runtimes](lambda-runtimes.md).

## Recursive loop notifications
<a name="invocation-recursion-monitoring"></a>

When Lambda stops a recursive loop, you receive notifications through the [Health Dashboard](https://aws.amazon.com/premiumsupport/technology/aws-health-dashboard/) and through email. You can also use CloudWatch metrics to monitor the number of recursive invocations that Lambda has stopped.

### Health Dashboard notifications
<a name="invocation-recursion-phd"></a>

When Lambda stops a recursive invocation, the Health Dashboard displays a notification on the **Your account health** page, under [Open and recent issues](https://health.aws.amazon.com/health/home#/account/dashboard/open-issues). Note that it can take up to 3.5 hours after Lambda stops a recursive invocation before this notification is displayed. For more information about viewing account events in the Health Dashboard, see [Getting started with your AWS Health Dashboard – Your account health](https://docs.aws.amazon.com/health/latest/ug/getting-started-health-dashboard.html) in the *AWS Health User Guide*.

### Email alerts
<a name="invocation-recursion-email"></a>

When Lambda first stops a recursive invocation of your function, it sends you an email alert. Lambda sends a maximum of one email every 24 hours for each function in your AWS account. After Lambda sends an email notification, you won't receive any more emails for that function for another 24 hours, even if Lambda stops further recursive invocations of the function. Note that it can take up to 3.5 hours after Lambda stops a recursive invocation before you receive this email alert.

Lambda sends recursive loop email alerts to your AWS account's primary account contact and alternate operations contact. For information about viewing or updating the email addresses in your account, see [Updating contact information](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-update-contact.html) in the *AWS General Reference*.

### Amazon CloudWatch metrics
<a name="invocation-recursion-cloudwatch"></a>

The [CloudWatch metric](monitoring-metrics-types.md) `RecursiveInvocationsDropped` records the number of function invocations that Lambda has stopped because your function has been invoked more than approximately 16 times in a single chain of requests. Lambda emits this metric as soon as it stops a recursive invocation. To view this metric, follow the instructions for [Viewing metrics on the CloudWatch console](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-console) and choose the metric `RecursiveInvocationsDropped`.

## Responding to recursive loop detection notifications
<a name="invocation-recursion-responding"></a>

When your function is invoked more than approximately 16 times by the same triggering event, Lambda stops the next function invocation for that event to break the recursive loop. To prevent a reoccurrence of a recursive loop that Lambda has broken, do the following: 
+ Reduce your function's available [concurrency](lambda-concurrency.md) to zero, which throttles all future invocations.
+ Remove or disable the trigger or event source mapping that's invoking your function.
+ Identify and fix code defects that write events back to the AWS resource that's invoking your function. A common source of defects occurs when you use variables to define a function's event source and target. Check that you're not using the same value for both variables.

Additionally, if the event source for your Lambda function is an Amazon SQS queue, then consider [configuring a dead-letter queue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue.html) on the source queue.

**Note**  
Make sure that you configure the dead-letter queue on the source queue, not on the Lambda function. The dead-letter queue that you configure on a function is used for the function's [asynchronous invocation queue](invocation-async.md), not for event source queues.

If the event source is an Amazon SNS topic, then consider adding an [on-failure destination](invocation-async-retain-records.md#invocation-async-destinations) for your function.

**To reduce your function's available concurrency to zero (console)**

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

1. Choose the name of your function.

1. Choose **Throttle**.

1. In the **Throttle your function** dialog box, choose **Confirm**.

**To remove a trigger or event source mapping for your function (console)**

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

1. Choose the name of your function.

1. Choose the **Configuration** tab, then choose **Triggers**.

1. Under **Triggers**, select the trigger or event source mapping that you want to delete, then choose **Delete**.

1. In the **Delete triggers** dialog box, choose **Delete**.

**To disable an event source mapping for your function (AWS CLI)**

1. To find the UUID for the event source mapping that you want to disable, run the AWS Command Line Interface (AWS CLI) [list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/list-event-source-mappings.html) command.

   ```
   aws lambda list-event-source-mappings
   ```

1. To disable the event source mapping, run the following AWS CLI [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) command.

   ```
   aws lambda update-event-source-mapping --function-name MyFunction \
   --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 --no-enabled
   ```

## Allowing a Lambda function to run in a recursive loop
<a name="invocation-recursion-disable"></a>

If your design intentionally uses a recursive loop, you can configure a Lambda function to allow it to be invoked recursively. We recommend that you avoid using recursive loops in your design. Implementation errors can lead to recursive invocations using all of your AWS account's available concurrency and to unexpected charges being billed to your account.

**Important**  
If you use recursive loops, treat them with caution. Implement best practice guard rails to minimize the risks of implementation errors. To learn more about best practices for using recursive patterns, see [Recursive patterns that cause run-away Lambda functions](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway) in Serverless Land.

You can configure functions to allow recursive loops using the Lambda console, the AWS Command Line Interface (AWS CLI), and the [PutFunctionRecursionConfig](https://docs.aws.amazon.com//lambda/latest/api/API_PutFunctionRecursionConfig.html) API. You can also configure a function's recursive loop detection setting in AWS SAM and CloudFormation. 

By default, Lambda detects and terminates recursive loops. Unless your design intentionally uses a recursive loop, we recommend that you don't change your functions' default configuration.

Note that when you configure a function to allow recursive loops, the [CloudWatch metric](monitoring-metrics-types.md#invocation-metrics) `RecursiveInvocationsDropped` isn't emitted.

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

**To allow a function to run in a recursive loop (console)**

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

1. Choose the name of your function to open the function detail page.

1. Choose the **Configuration** tab, then choose **Concurrency and recursion detection**.

1. Beside **Recursive loop detection**, choose **Edit**.

1. Select **Allow recursive loops**.

1. Choose **Save**.

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

You can use the [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API to allow your function to be invoked in a recursive loop. Specify `Allow` for the recursive loop parameter. For example, you can call this API with the `put-function-recursion-config` AWS CLI command:

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Allow
```

------

You can change your function's configuration back to the default setting so that Lambda terminates recursive loops when it detects them. Edit your function's configuration using the Lambda console or the AWS CLI.

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

**To configure a function so that recursive loops are terminated (console)**

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

1. Choose the name of your function to open the function detail page.

1. Choose the **Configuration** tab, then choose **Concurrency and recursion detection**.

1. Beside **Recursive loop detection**, choose **Edit**.

1. Select **Terminate recursive loops**.

1. Choose **Save**.

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

You can use the [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API to configure your function so that Lambda terminates recursive loops when it detects them. Specify `Terminate` for the recursive loop parameter. For example, you can call this API with the `put-function-recursion-config` AWS CLI command:

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Terminate
```

------

## Supported Regions for Lambda recursive loop detection
<a name="invocation-recursion-regions"></a>

Lambda recursive loop detection is supported in all [commercial Regions](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#region) except Mexico (Central) and Asia Pacific (New Zealand).

# Creating and managing Lambda function URLs
<a name="urls-configuration"></a>

A function URL is a dedicated HTTP(S) endpoint for your Lambda function. You can create and configure a function URL through the Lambda console or the Lambda API.

**Tip**  
Lambda offers two ways to invoke your function through an HTTP endpoint: function URLs and Amazon API Gateway. If you're not sure which is the best method for your use case, see [Select a method to invoke your Lambda function using an HTTP request](furls-http-invoke-decision.md).

When you create a function URL, Lambda automatically generates a unique URL endpoint for you. Once you create a function URL, its URL endpoint never changes. Function URL endpoints have the following format:

```
https://<url-id>.lambda-url.<region>.on.aws
```

**Note**  
Function URLs are not supported in the following AWS Regions: Asia Pacific (Hyderabad) (`ap-south-2`), Asia Pacific (Melbourne) (`ap-southeast-4`), Asia Pacific (Malaysia) (`ap-southeast-5`), Asia Pacific (New Zealand) (`ap-southeast-6`), Asia Pacific (Thailand) (`ap-southeast-7`), Asia Pacific (Taipei) (`ap-east-2`), Canada West (Calgary) (`ca-west-1`), Europe (Spain) (`eu-south-2`), Europe (Zurich) (`eu-central-2`), Israel (Tel Aviv) (`il-central-1`), and Middle East (UAE) (`me-central-1`).

Function URLs are dual stack-enabled, supporting IPv4 and IPv6. After you configure a function URL for your function, you can invoke your function through its HTTP(S) endpoint via a web browser, curl, Postman, or any HTTP client.

**Note**  
You can access your function URL through the public Internet only. While Lambda functions do support AWS PrivateLink, function URLs do not.

Lambda function URLs use [resource-based policies](access-control-resource-based.md) for security and access control. Function URLs also support cross-origin resource sharing (CORS) configuration options.

You can apply function URLs to any function alias, or to the `$LATEST` unpublished function version. You can't add a function URL to any other function version.

The following section show how to create and manage a function URL using the Lambda console, AWS CLI, and CloudFormation template

**Topics**
+ [

## Creating a function URL (console)
](#create-url-console)
+ [

## Creating a function URL (AWS CLI)
](#create-url-cli)
+ [

## Adding a function URL to a CloudFormation template
](#urls-cfn)
+ [

## Cross-origin resource sharing (CORS)
](#urls-cors)
+ [

## Throttling function URLs
](#urls-throttling)
+ [

## Deactivating function URLs
](#urls-deactivating)
+ [

## Deleting function URLs
](#w2aac39c81c53)
+ [

# Control access to Lambda function URLs
](urls-auth.md)
+ [

# Invoking Lambda function URLs
](urls-invocation.md)
+ [

# Monitoring Lambda function URLs
](urls-monitoring.md)
+ [

# Select a method to invoke your Lambda function using an HTTP request
](furls-http-invoke-decision.md)
+ [

# Tutorial: Creating a webhook endpoint using a Lambda function URL
](urls-webhook-tutorial.md)

## Creating a function URL (console)
<a name="create-url-console"></a>

Follow these steps to create a function URL using the console.

### To create a function URL for an existing function
<a name="create-url-existing-function"></a>

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 create the function URL for.

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

1. Choose **Create function URL**.

1. For **Auth type**, choose **AWS\$1IAM** or **NONE**. For more information about function URL authentication, see [Access control](urls-auth.md).

1. (Optional) Select **Configure cross-origin resource sharing (CORS)**, and then configure the CORS settings for your function URL. For more information about CORS, see [Cross-origin resource sharing (CORS)](#urls-cors).

1. Choose **Save**.

This creates a function URL for the `$LATEST` unpublished version of your function. The function URL appears in the **Function overview** section of the console.

### To create a function URL for an existing alias
<a name="create-url-existing-alias"></a>

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

1. Choose the name of the function with the alias that you want to create the function URL for.

1. Choose the **Aliases** tab, and then choose the name of the alias that you want to create the function URL for.

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

1. Choose **Create function URL**.

1. For **Auth type**, choose **AWS\$1IAM** or **NONE**. For more information about function URL authentication, see [Access control](urls-auth.md).

1. (Optional) Select **Configure cross-origin resource sharing (CORS)**, and then configure the CORS settings for your function URL. For more information about CORS, see [Cross-origin resource sharing (CORS)](#urls-cors).

1. Choose **Save**.

This creates a function URL for your function alias. The function URL appears in the console's **Function overview** section for your alias.

### To create a new function with a function URL
<a name="create-url-new-function"></a>

**To create a new function with a function URL (console)**

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

1. Choose **Create function**.

1. Under **Basic information**, do the following:

   1. For **Function name**, enter a name for your function, such as **my-function**.

   1. For **Runtime**, choose the language runtime that you prefer, such as **Node.js 24**.

   1. For **Architecture**, choose either **x86\$164** or **arm64**.

   1. Expand **Permissions**, then choose whether to create a new execution role or use an existing one.

1. Expand **Advanced settings**, and then select **Function URL**.

1. For **Auth type**, choose **AWS\$1IAM** or **NONE**. For more information about function URL authentication, see [Access control](urls-auth.md).

1. (Optional) Select **Configure cross-origin resource sharing (CORS)**. By selecting this option during function creation, your function URL allows requests from all origins by default. You can edit the CORS settings for your function URL after creating the function. For more information about CORS, see [Cross-origin resource sharing (CORS)](#urls-cors).

1. Choose **Create function**.

This creates a new function with a function URL for the `$LATEST` unpublished version of the function. The function URL appears in the **Function overview** section of the console.

## Creating a function URL (AWS CLI)
<a name="create-url-cli"></a>

To create a function URL for an existing Lambda function using the AWS Command Line Interface (AWS CLI), run the following command:

```
aws lambda create-function-url-config \
    --function-name my-function \
    --qualifier prod \ // optional
    --auth-type AWS_IAM
    --cors-config {AllowOrigins="https://example.com"} // optional
```

This adds a function URL to the **prod** qualifier for the function **my-function**. For more information about these configuration parameters, see [CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html) in the API reference.

**Note**  
To create a function URL via the AWS CLI, the function must already exist.

## Adding a function URL to a CloudFormation template
<a name="urls-cfn"></a>

To add an `AWS::Lambda::Url` resource to your CloudFormation template, use the following syntax:

### JSON
<a name="urls-cfn-json"></a>

```
{
  "Type" : "AWS::Lambda::Url",
  "Properties" : {
      "AuthType" : String,
      "Cors" : Cors,
      "Qualifier" : String,
      "TargetFunctionArn" : String
    }
}
```

### YAML
<a name="urls-cfn-yaml"></a>

```
Type: AWS::Lambda::Url
Properties: 
  AuthType: String
  Cors: 
    Cors
  Qualifier: String
  TargetFunctionArn: String
```

### Parameters
<a name="urls-cfn-params"></a>
+ (Required) `AuthType` – Defines the type of authentication for your function URL. Possible values are either `AWS_IAM` or `NONE`. To restrict access to authenticated users only, set to `AWS_IAM`. To bypass IAM authentication and allow any user to make requests to your function, set to `NONE`.
+ (Optional) `Cors` – Defines the [CORS settings](#urls-cors) for your function URL. To add `Cors` to your `AWS::Lambda::Url` resource in CloudFormation, use the following syntax.

    
**Example AWS::Lambda::Url.Cors (JSON)**  

  ```
  {
    "AllowCredentials" : Boolean,
    "AllowHeaders" : [ String, ... ],
    "AllowMethods" : [ String, ... ],
    "AllowOrigins" : [ String, ... ],
    "ExposeHeaders" : [ String, ... ],
    "MaxAge" : Integer
  }
  ```  
**Example AWS::Lambda::Url.Cors (YAML)**  

  ```
    AllowCredentials: Boolean
    AllowHeaders: 
      - String
    AllowMethods: 
      - String
    AllowOrigins: 
      - String
    ExposeHeaders: 
      - String
    MaxAge: Integer
  ```
+ (Optional) `Qualifier` – The alias name.
+ (Required) `TargetFunctionArn` – The name or Amazon Resource Name (ARN) of the Lambda function. Valid name formats include the following:
  + **Function name** – `my-function`
  + **Function ARN** – `arn:aws:lambda:us-west-2:123456789012:function:my-function`
  + **Partial ARN** – `123456789012:function:my-function`

## Cross-origin resource sharing (CORS)
<a name="urls-cors"></a>

To define how different origins can access your function URL, use [cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). We recommend configuring CORS if you intend to call your function URL from a different domain. Lambda supports the following CORS headers for function URLs.


| CORS header | CORS configuration property | Example values | 
| --- | --- | --- | 
|  [ Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)  |  `AllowOrigins`  |  `*` (allow all origins) `https://www.example.com` `http://localhost:60905`  | 
|  [ Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)  |  `AllowMethods`  |  `GET`, `POST`, `DELETE`, `*`  | 
|  [ Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)  |  `AllowHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)  |  `ExposeHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials)  |  `AllowCredentials`  |  `TRUE`  | 
|  [ Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)  |  `MaxAge`  |  `5` (default), `300`  | 

When you configure CORS for a function URL using the Lambda console or the AWS CLI, Lambda automatically adds the CORS headers to all responses through the function URL. Alternatively, you can manually add CORS headers to your function response. If there are conflicting headers, the expected behavior depends on the type of request:
+ For preflight requests such as OPTIONS requests, the configured CORS headers on the function URL take precedence. Lambda returns only these CORS headers in the response.
+ For non-preflight requests such as GET or POST requests, Lambda returns both the configured CORS headers on the function URL, as well as the CORS headers returned by the function. This can result in duplicate CORS headers in the response. You may see an error similar to the following: `The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed`.

In general, we recommend configuring all CORS settings on the function URL, rather than sending CORS headers manually in the function response.

## Throttling function URLs
<a name="urls-throttling"></a>

Throttling limits the rate at which your function processes requests. This is useful in many situations, such as preventing your function from overloading downstream resources, or handling a sudden surge in requests.

You can throttle the rate of requests that your Lambda function processes through a function URL by configuring reserved concurrency. Reserved concurrency limits the number of maximum concurrent invocations for your function. Your function's maximum request rate per second (RPS) is equivalent to 10 times the configured reserved concurrency. For example, if you configure your function with a reserved concurrency of 100, then the maximum RPS is 1,000.

Whenever your function concurrency exceeds the reserved concurrency, your function URL returns an HTTP `429` status code. If your function receives a request that exceeds the 10x RPS maximum based on your configured reserved concurrency, you also receive an HTTP `429` error. For more information about reserved concurrency, see [Configuring reserved concurrency for a function](configuration-concurrency.md).

## Deactivating function URLs
<a name="urls-deactivating"></a>

In an emergency, you might want to reject all traffic to your function URL. To deactivate your function URL, set the reserved concurrency to zero. This throttles all requests to your function URL, resulting in HTTP `429` status responses. To reactivate your function URL, delete the reserved concurrency configuration, or set the configuration to an amount greater than zero.

## Deleting function URLs
<a name="w2aac39c81c53"></a>

When you delete a function URL, you can’t recover it. Creating a new function URL will result in a different URL address.

**Note**  
If you delete a function URL with auth type `NONE`, Lambda doesn't automatically delete the associated resource-based policy. If you want to delete this policy, you must manually do so.

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

1. Choose the name of the function.

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

1. Choose **Delete**.

1. Enter the word *delete* into the field to confirm the deletion.

1. Choose **Delete**.

**Note**  
When you delete a function that has a function URL, Lambda asynchronously deletes the function URL. If you immediately create a new function with the same name in the same account, it is possible that the original function URL will be mapped to the new function instead of deleted.

# Control access to Lambda function URLs
<a name="urls-auth"></a>

**Note**  
Starting in October 2025, new function URLs will require both `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions.

You can control access to your Lambda function URLs using the [AuthType](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html#lambda-CreateFunctionUrlConfig-request-AuthType) parameter combined with [resource-based policies](access-control-resource-based.md) attached to your specific function. The configuration of these two components determines who can invoke or perform other administrative actions on your function URL.

The `AuthType` parameter determines how Lambda authenticates or authorizes requests to your function URL. When you configure your function URL, you must specify one of the following `AuthType` options:
+ `AWS_IAM` – Lambda uses AWS Identity and Access Management (IAM) to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy. Choose this option if you want only authenticated users and roles to invoke your function using the function URL.
+ `NONE` – Lambda doesn't perform any authentication before invoking your function. However, your function's resource-based policy is always in effect and must grant public access before your function URL can receive requests. Choose this option to allow public, unauthenticated access to your function URL.

For additional insights into security, you can use AWS Identity and Access Management Access Analyzer to get a comprehensive analysis of external access to your function URL. IAM Access Analyzer also monitors for new or updated permissions on your Lambda functions to help you identify permissions that grant public and cross-account access. You can use IAM Access Analyzer at no charge. To get started with IAM Access Analyzer, see [Using AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html).

This page contains examples of resource-based policies for both auth types, and how to create these policies using the [AddPermission](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html) API operation or the Lambda console. For information about how to invoke your function URL after you've set up permissions, see [Invoking Lambda function URLs](urls-invocation.md).

**Topics**
+ [

## Using the `AWS_IAM` auth type
](#urls-auth-iam)
+ [

## Using the `NONE` auth type
](#urls-auth-none)
+ [

## Governance and access control
](#urls-governance)

## Using the `AWS_IAM` auth type
<a name="urls-auth-iam"></a>

If you choose the `AWS_IAM` auth type, users who need to invoke your Lambda function URL must have the `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions. Depending on who makes the invocation request, you might have to grant this permission using a [resource-based policy](access-control-resource-based.md).

If the principal making the request is in the same AWS account as the function URL, then the principal must **either** have `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions in their [identity-based policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html), **or** have permissions granted to them in the function's resource-based policy. In other words, a resource-based policy is optional if the user already has `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions in their identity-based policy. Policy evaluation follows the rules outlined in [Policy evaluation logic](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html).

If the principal making the request is in a different account, then the principal must have **both** an identity-based policy that gives them `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions **and** permissions granted to them in a resource-based policy on the function that they are trying to invoke. Policy evaluation follows the rules outlined in [Determining whether a cross-account request is allowed](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html#policy-eval-cross-account).

The following resource-based policy allows the `example` role in AWS account `444455556666` to invoke the function URL associated with function `my-function`. The [lambda:InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) context key restricts the `lambda:InvokeFunction` action to function URL calls. This means that the principal must use the function URL to invoke the function. If you don't include `lambda:InvokedViaFunctionUrl`, the principal can invoke your function through other invocation methods, in addition to the function URL.

**Example — Cross-account resource-based policy**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "AWS_IAM"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

You can create this resource-based policy through the console using the following steps:

**To grant URL invocation permissions to another account (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 grant URL invocation permissions for.

1. Choose the **Configuration** tab, and then choose **Permissions**.

1. Under **Resource-based policy**, choose **Add permissions**.

1. Choose **Function URL**.

1. For **Auth type**, choose **AWS\$1IAM**.

1. Enter a **Statement ID** for your policy statement.

1. For **Principal**, enter the account ID or the Amazon Resource Name (ARN) of the user or role that you want to grant permissions to. For example: **444455556666**.

1. Choose **Save**.

Alternatively, you can create this policy using the following [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) AWS Command Line Interface (AWS CLI) commands. When you use the AWS CLI, you must add the `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` statements separately. For example:

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

```
aws lambda add-permission --function-name my-function \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal 444455556666 \
  --invoked-via-function-url
```

## Using the `NONE` auth type
<a name="urls-auth-none"></a>

**Important**  
When your function URL auth type is `NONE` and you have a [resource-based policy](access-control-resource-based.md) that grants public access, any unauthenticated user with your function URL can invoke your function.

In some cases, you might want your function URL to be public. For example, you might want to serve requests made directly from a web browser. To allow public access to your function URL, choose the `NONE` auth type.

If you choose the `NONE` auth type, Lambda doesn't use IAM to authenticate requests to your function URL. However, your function must have a resource-based policy that allows `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction`. When you create a function URL with auth type `NONE` using the console or AWS Serverless Application Model (AWS SAM), Lambda automatically creates the resource-based policy for you. If you're using the AWS CLI, AWS CloudFormation, or the Lambda API directly, you must [add the policy yourself](#policy-cli).

We recommend that you include the [lambda:InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) context key in your resource-based policies when using the `NONE` auth type. This context key ensures that the function can only be invoked through the function URL and not through other invocation methods.

Note the following about this policy:
+ All entities can call `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction`. This means that anyone who has your function URL can invoke your function.
+ The `lambda:FunctionUrlAuthType` condition key value is `NONE`. This means that the policy statement allows access only when your function URL's auth type is also `NONE`.
+ The `lambda:InvokedViaFunctionUrl` condition ensures that the function can only be invoked through the function URL and not through other invocation methods.

**Example — Default resource-based policy for NONE auth type**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "NONE"
        }
      }
    },
    {
      "Sid": "FunctionURLInvokeAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

**Create the resource-based policy using the AWS CLI**  
Unless you use the console or AWS SAM to create a function URL with auth type `NONE`, you must add the resource-based policy yourself. Use the following commands to create statements for the `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions. Each statement must be added in a separate command.

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeURL \
  --action lambda:InvokeFunctionUrl \
  --principal * \
  --function-url-auth-type NONE
```

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal * \
  --invoked-via-function-url
```

**Note**  
If you delete a function URL with auth type `NONE`, Lambda doesn't automatically delete the associated resource-based policy. If you want to delete this policy, you must manually do so.

If a function's resource-based policy doesn't grant `lambda:invokeFunctionUrl` and `lambda:InvokeFunction` permissions, users will get a 403 Forbidden error code when they try to invoke your function URL. This will occur even if the function URL uses the `NONE` auth type.

## Governance and access control
<a name="urls-governance"></a>

In addition to function URL invocation permissions, you can also control access on actions used to configure function URLs. Lambda supports the following IAM policy actions for function URLs:
+ `lambda:InvokeFunctionUrl` – Invoke a Lambda function using the function URL.
+ `lambda:CreateFunctionUrlConfig` – Create a function URL and set its `AuthType`.
+ `lambda:UpdateFunctionUrlConfig` – Update a function URL configuration and its `AuthType`.
+ `lambda:GetFunctionUrlConfig` – View the details of a function URL.
+ `lambda:ListFunctionUrlConfigs` – List function URL configurations.
+ `lambda:DeleteFunctionUrlConfig` – Delete a function URL.

To allow or deny function URL access to other AWS entities, include these actions in IAM policies. For example, the following policy grants the `example` role in AWS account `444455556666` permissions to update the function URL for function **my-function** in account `123456789012`.

**Example cross-account function URL policy**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action": "lambda:UpdateFunctionUrlConfig",
            "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function"
        }
    ]
}
```

### Condition keys
<a name="urls-condition-keys"></a>

For fine-grained access control over your function URLs, use condition context keys. Lambda supports the following context keys for function URLs:
+ `lambda:FunctionUrlAuthType` – Defines an enum value describing the auth type that your function URL uses. The value can be either `AWS_IAM` or `NONE`.
+ `lambda:InvokedViaFunctionUrl` – Restricts the `lambda:InvokeFunction` action to calls made through the function URL. This ensures that the function can only be invoked using the function URL and not through other invocation methods. For examples of resource-based policies that use the `lambda:InvokedViaFunctionUrl` context key, see the examples in [Using the `AWS_IAM` auth type](#urls-auth-iam) and [Using the `NONE` auth type](#urls-auth-none).

You can use these context keys in policies associated with your function. For example, you might want to restrict who can make configuration changes to your function URLs. To deny all `UpdateFunctionUrlConfig` requests to any function with URL auth type `NONE`, you can define the following policy:

**Example function URL policy with explicit deny**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action":[
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "NONE"
                }
            }
        }
    ]
}
```

To grant the `example` role in AWS account `444455556666` permissions to make `CreateFunctionUrlConfig` and `UpdateFunctionUrlConfig` requests on functions with URL auth type `AWS_IAM`, you can define the following policy:

**Example function URL policy with explicit allow**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

You can also use this condition key in a [service control policy](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) (SCP). Use SCPs to manage permissions across an entire organization in AWS Organizations. For example, to deny users from creating or updating function URLs that use anything other than the `AWS_IAM` auth type, use the following service control policy:

**Example function URL SCP with explicit deny**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:*:123456789012:function:*",
            "Condition": {
                "StringNotEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

# Invoking Lambda function URLs
<a name="urls-invocation"></a>

A function URL is a dedicated HTTP(S) endpoint for your Lambda function. You can create and configure a function URL through the Lambda console or the Lambda API.

**Tip**  
Lambda offers two ways to invoke your function through an HTTP endpoint: function URLs and Amazon API Gateway. If you're not sure which is the best method for your use case, see [Select a method to invoke your Lambda function using an HTTP request](furls-http-invoke-decision.md).

When you create a function URL, Lambda automatically generates a unique URL endpoint for you. Once you create a function URL, its URL endpoint never changes. Function URL endpoints have the following format:

```
https://<url-id>.lambda-url.<region>.on.aws
```

**Note**  
Function URLs are not supported in the following AWS Regions: Asia Pacific (Hyderabad) (`ap-south-2`), Asia Pacific (Melbourne) (`ap-southeast-4`), Asia Pacific (Malaysia) (`ap-southeast-5`), Asia Pacific (New Zealand) (`ap-southeast-6`), Asia Pacific (Thailand) (`ap-southeast-7`), Asia Pacific (Taipei) (`ap-east-2`), Canada West (Calgary) (`ca-west-1`), Europe (Spain) (`eu-south-2`), Europe (Zurich) (`eu-central-2`), Israel (Tel Aviv) (`il-central-1`), and Middle East (UAE) (`me-central-1`).

Function URLs are dual stack-enabled, supporting IPv4 and IPv6. After configuring your function URL, you can invoke your function through its HTTP(S) endpoint via a web browser, curl, Postman, or any HTTP client. To invoke a function URL, you must have `lambda:InvokeFunctionUrl` and `lambda:InvokeFunction` permissions. For more information, see [Access control](urls-auth.md).

**Topics**
+ [

## Function URL invocation basics
](#urls-invocation-basics)
+ [

## Request and response payloads
](#urls-payloads)

## Function URL invocation basics
<a name="urls-invocation-basics"></a>

If your function URL uses the `AWS_IAM` auth type, you must sign each HTTP request using [AWS Signature Version 4 (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html). Tools such as [Postman](https://quickstarts.postman.com/guide/aws/index.html?index=..%2F..index#2) offer built-in ways to sign your requests with SigV4.

If you don't use a tool to sign HTTP requests to your function URL, you must manually sign each request using SigV4. When your function URL receives a request, Lambda also calculates the SigV4 signature. Lambda processes the request only if the signatures match. For instructions on how to manually sign your requests with SigV4, see [Signing AWS requests with Signature Version 4](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html) in the *Amazon Web Services General Reference Guide*.

If your function URL uses the `NONE` auth type, you don't have to sign your requests using SigV4. You can invoke your function using a web browser, curl, Postman, or any HTTP client.

To test simple `GET` requests to your function, use a web browser. For example, if your function URL is `https://abcdefg.lambda-url.us-east-1.on.aws`, and it takes in a string parameter `message`, your request URL could look like this:

```
https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld
```

To test other HTTP requests, such as a `POST` request, you can use a tool such as curl. For example, if you want to include some JSON data in a `POST` request to your function URL, you could use the following curl command:

```
curl -v 'https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld' \
-H 'content-type: application/json' \
-d '{ "example": "test" }'
```

## Request and response payloads
<a name="urls-payloads"></a>

When a client calls your function URL, Lambda maps the request to an event object before passing it to your function. Your function's response is then mapped to an HTTP response that Lambda sends back to the client through the function URL.

The request and response event formats follow the same schema as the [Amazon API Gateway payload format version 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format).

### Request payload format
<a name="urls-request-payload"></a>

A request payload has the following structure:

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "<urlid>",
    "authentication": null,
    "authorizer": {
        "iam": {
                "accessKey": "AKIA...",
                "accountId": "111122223333",
                "callerId": "AIDA...",
                "cognitoIdentity": null,
                "principalOrgId": null,
                "userArn": "arn:aws:iam::111122223333:user/example-user",
                "userId": "AIDA..."
        }
    },
    "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
    "domainPrefix": "<url-id>",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "123.123.123.123",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from client!",
  "pathParameters": null,
  "isBase64Encoded": false,
  "stageVariables": null
}
```


| Parameter | Description | Example | 
| --- | --- | --- | 
|  `version`  |  The payload format version for this event. Lambda function URLs currently support [payload format version 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format).  |  `2.0`  | 
|  `routeKey`  |  Function URLs don't use this parameter. Lambda sets this to `$default` as a placeholder.  |  `$default`  | 
|  `rawPath`  |  The request path. For example, if the request URL is `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`, then the raw path value is `/example/test/demo`.  |  `/example/test/demo`  | 
|  `rawQueryString`  |  The raw string containing the request's query string parameters. Supported characters include `a-z`, `A-Z`, `0-9`, `.`, `_`, `-`, `%`, `&`, `=`, and `+`.  |  `"?parameter1=value1&parameter2=value2"`  | 
|  `cookies`  |  An array containing all cookies sent as part of the request.  |  `["Cookie_1=Value_1", "Cookie_2=Value_2"]`  | 
|  `headers`  |  The list of request headers, presented as key-value pairs.  |  `{"header1": "value1", "header2": "value2"}`  | 
|  `queryStringParameters`  |  The query parameters for the request. For example, if the request URL is `https://{url-id}.lambda-url.{region}.on.aws/example?name=Jane`, then the `queryStringParameters` value is a JSON object with a key of `name` and a value of `Jane`.  |  `{"name": "Jane"}`  | 
|  `requestContext`  |  An object that contains additional information about the request, such as the `requestId`, the time of the request, and the identity of the caller if authorized via AWS Identity and Access Management (IAM).  |   | 
|  `requestContext.accountId`  |  The AWS account ID of the function owner.  |  `"123456789012"`  | 
|  `requestContext.apiId`  |  The ID of the function URL.  |  `"33anwqw8fj"`  | 
|  `requestContext.authentication`  |  Function URLs don't use this parameter. Lambda sets this to `null`.  |  `null`  | 
|  `requestContext.authorizer`  |  An object that contains information about the caller identity, if the function URL uses the `AWS_IAM` auth type. Otherwise, Lambda sets this to `null`.  |   | 
|  `requestContext.authorizer.iam.accessKey`  |  The access key of the caller identity.  |  `"AKIAIOSFODNN7EXAMPLE"`  | 
|  `requestContext.authorizer.iam.accountId`  |  The AWS account ID of the caller identity.  |  `"111122223333"`  | 
|  `requestContext.authorizer.iam.callerId`  |  The ID (user ID) of the caller.  |  `"AIDACKCEVSQ6C2EXAMPLE"`  | 
|  `requestContext.authorizer.iam.cognitoIdentity`  |  Function URLs don't use this parameter. Lambda sets this to `null` or excludes this from the JSON.  |  `null`  | 
|  `requestContext.authorizer.iam.principalOrgId`  |  The principal org ID associated with the caller identity.  |  `"AIDACKCEVSQORGEXAMPLE"`  | 
|  `requestContext.authorizer.iam.userArn`  |  The user Amazon Resource Name (ARN) of the caller identity.  |  `"arn:aws:iam::111122223333:user/example-user"`  | 
|  `requestContext.authorizer.iam.userId`  |  The user ID of the caller identity.  |  `"AIDACOSFODNN7EXAMPLE2"`  | 
|  `requestContext.domainName`  |  The domain name of the function URL.  |  `"<url-id>.lambda-url.us-west-2.on.aws"`  | 
|  `requestContext.domainPrefix`  |  The domain prefix of the function URL.  |  `"<url-id>"`  | 
|  `requestContext.http`  |  An object that contains details about the HTTP request.  |   | 
|  `requestContext.http.method`  |  The HTTP method used in this request. Valid values include `GET`, `POST`, `PUT`, `HEAD`, `OPTIONS`, `PATCH`, and `DELETE`.  |  `GET`  | 
|  `requestContext.http.path`  |  The request path. For example, if the request URL is `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`, then the path value is `/example/test/demo`.  |  `/example/test/demo`  | 
|  `requestContext.http.protocol`  |  The protocol of the request.  |  `HTTP/1.1`  | 
|  `requestContext.http.sourceIp`  |  The source IP address of the immediate TCP connection making the request.  |  `123.123.123.123`  | 
|  `requestContext.http.userAgent`  |  The User-Agent request header value.  |  `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Gecko/20100101 Firefox/42.0`  | 
|  `requestContext.requestId`  |  The ID of the invocation request. You can use this ID to trace invocation logs related to your function.  |  `e1506fd5-9e7b-434f-bd42-4f8fa224b599`  | 
|  `requestContext.routeKey`  |  Function URLs don't use this parameter. Lambda sets this to `$default` as a placeholder.  |  `$default`  | 
|  `requestContext.stage`  |  Function URLs don't use this parameter. Lambda sets this to `$default` as a placeholder.  |  `$default`  | 
|  `requestContext.time`  |  The timestamp of the request.  |  `"07/Sep/2021:22:50:22 +0000"`  | 
|  `requestContext.timeEpoch`  |  The timestamp of the request, in Unix epoch time.  |  `"1631055022677"`  | 
|  `body`  |  The body of the request. If the content type of the request is binary, the body is base64-encoded.  |  `{"key1": "value1", "key2": "value2"}`  | 
|  `pathParameters`  |  Function URLs don't use this parameter. Lambda sets this to `null` or excludes this from the JSON.  |  `null`  | 
|  `isBase64Encoded`  |  `TRUE` if the body is a binary payload and base64-encoded. `FALSE` otherwise.  |  `FALSE`  | 
|  `stageVariables`  |  Function URLs don't use this parameter. Lambda sets this to `null` or excludes this from the JSON.  |  `null`  | 

### Response payload format
<a name="urls-response-payload"></a>

When your function returns a response, Lambda parses the response and converts it into an HTTP response. Function response payloads have the following format:

```
{
   "statusCode": 201,
    "headers": {
        "Content-Type": "application/json",
        "My-Custom-Header": "Custom Value"
    },
    "body": "{ \"message\": \"Hello, world!\" }",
    "cookies": [
        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",
        "Cookie_2=Value2; Max-Age=78000"
    ],
    "isBase64Encoded": false
}
```

Lambda infers the response format for you. If your function returns valid JSON and doesn't return a `statusCode`, Lambda assumes the following:
+ `statusCode` is `200`.
**Note**  
The valid `statusCode` are within the range of 100 to 599.
+ `content-type` is `application/json`.
+ `body` is the function response.
+ `isBase64Encoded` is `false`.

The following examples show how the output of your Lambda function maps to the response payload, and how the response payload maps to the final HTTP response. When the client invokes your function URL, they see the HTTP response.

**Example output for a string response**


| Lambda function output | Interpreted response output | HTTP response (what the client sees) | 
| --- | --- | --- | 
|  <pre>"Hello, world!"</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": "Hello, world!",<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 15<br /><br />"Hello, world!"</pre>  | 

**Example output for a JSON response**


| Lambda function output | Interpreted response output | HTTP response (what the client sees) | 
| --- | --- | --- | 
|  <pre>{<br />  "message": "Hello, world!"<br />}</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": {<br />    "message": "Hello, world!"<br />  },<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 34<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

**Example output for a custom response**


| Lambda function output | Interpreted response output | HTTP response (what the client sees) | 
| --- | --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

### Cookies
<a name="urls-cookies"></a>

To return cookies from your function, don't manually add `set-cookie` headers. Instead, include the cookies in your response payload object. Lambda automatically interprets this and adds them as `set-cookie` headers in your HTTP response, as in the following example.


| Lambda function output | HTTP response (what the client sees) | 
| --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "cookies": [<br />        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",<br />        "Cookie_2=Value2; Max-Age=78000"<br />    ],<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br />set-cookie: Cookie_1=Value2; Expires=21 Oct 2021 07:48 GMT<br />set-cookie: Cookie_2=Value2; Max-Age=78000<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

# Monitoring Lambda function URLs
<a name="urls-monitoring"></a>

You can use AWS CloudTrail and Amazon CloudWatch to monitor your function URLs.

**Topics**
+ [

## Monitoring function URLs with CloudTrail
](#urls-cloudtrail)
+ [

## CloudWatch metrics for function URLs
](#urls-cloudwatch)

## Monitoring function URLs with CloudTrail
<a name="urls-cloudtrail"></a>

For function URLs, Lambda automatically supports logging the following API operations as events in CloudTrail log files:
+ [CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html)
+ [UpdateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionUrlConfig.html)
+ [DeleteFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteFunctionUrlConfig.html)
+ [GetFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionUrlConfig.html)
+ [ListFunctionUrlConfigs](https://docs.aws.amazon.com/lambda/latest/api/API_ListFunctionUrlConfigs.html)

Each log entry contains information about the caller identity, when the request was made, and other details. You can see all events within the last 90 days by viewing your CloudTrail **Event history**. To retain records past 90 days, you can create a trail.

By default, CloudTrail doesn't log `InvokeFunctionUrl` requests, which are considered data events. However, you can turn on data event logging in CloudTrail. For more information, see [Logging data events for trails](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html) in the *AWS CloudTrail User Guide*.

## CloudWatch metrics for function URLs
<a name="urls-cloudwatch"></a>

Lambda sends aggregated metrics about function URL requests to CloudWatch. With these metrics, you can monitor your function URLs, build dashboards, and configure alarms in the CloudWatch console.

Function URLs support the following invocation metrics. We recommend viewing these metrics with the `Sum` statistic.
+ `UrlRequestCount` – The number of requests made to this function URL.
+ `Url4xxCount` – The number of requests that returned a 4XX HTTP status code. 4XX series codes indicate client-side errors, such as bad requests.
+ `Url5xxCount` – The number of requests that returned a 5XX HTTP status code. 5XX series codes indicate server-side errors, such as function errors and timeouts.

Function URLs also support the following performance metric. We recommend viewing this metric with the `Average` or `Max` statistics.
+ `UrlRequestLatency` – The time between when the function URL receives a request and when the function URL returns a response.

Each of these invocation and performance metrics supports the following dimensions:
+ `FunctionName` – View aggregate metrics for function URLs assigned to a function's `$LATEST` unpublished version, or to any of the function's aliases. For example, `hello-world-function`.
+ `Resource` – View metrics for a specific function URL. This is defined by a function name, along with either the function's `$LATEST` unpublished version or one of the function's aliases. For example, `hello-world-function:$LATEST`.
+ `ExecutedVersion` – View metrics for a specific function URL based on the executed version. You can use this dimension primarily to track the function URL assigned to the `$LATEST` unpublished version.

# Select a method to invoke your Lambda function using an HTTP request
<a name="furls-http-invoke-decision"></a>

Many common use cases for Lambda involve invoking your function using an HTTP request. For example, you might want a web application to invoke your function through a browser request. Lambda functions can also be used to create full REST APIs, handle user interactions from mobile apps, process data from external services via HTTP calls, or create custom webhooks.

The following sections explain what your choices are for invoking Lambda through HTTP and provide information to help you make the right decision for your particular use case.

## What are your choices when selecting an HTTP invoke method?
<a name="w2aac39c81c73b9"></a>

Lambda offers two main methods to invoke a function using an HTTP request - [function URLs](urls-configuration.md) and [API Gateway](services-apigateway.md). The key differences between these two options are as follows:
+ **Lambda function URLs** provide a simple, direct HTTP endpoint for a Lambda function. They are optimized for simplicity and cost-effectiveness and provide the fastest path to expose a Lambda function via HTTP.
+ **API Gateway** is a more advanced service for building fully-featured APIs. API Gateway is optimized for building and managing productions APIs at scale and provides comprehensive tools for security, monitoring, and traffic management.

## Recommendations if you already know your requirements
<a name="w2aac39c81c73c11"></a>

If you're already clear on your requirements, here are our basic recommendations:

We recommend **[function URLs](urls-configuration.md)** for simple applications or prototyping where you only need basic authentication methods and request/response handling and where you want to keep costs and complexity to a minimum.

**[API Gateway](services-apigateway.md)** is a better choice for production applications at scale or for cases where you need more advanced features like [OpenAPI Description](https://www.openapis.org/) support, a choice of authentication options, custom domain names, or rich request/response handling including throttling, caching, and request/response transformation.

## What to consider when selecting a method to invoke your Lambda function
<a name="w2aac39c81c73c13"></a>

When selecting between function URLs and API Gateway, you need to consider the following factors:
+ Your authentication needs, such as whether you require OAuth or Amazon Cognito to authenticate users
+ Your scaling requirements and the complexity of the API you want to implement
+ Whether you need advanced features such as request validation and request/response formatting
+ Your monitoring requirements
+ Your cost goals

By understanding these factors, you can select the option that best balances your security, complexity, and cost requirements.

The following information summarizes the main differences between the two options.

### Authentication
<a name="w2aac39c81c73c13c11b1"></a>
+ **Function URLs** provide basic authentication options through AWS Identity and Access Management (IAM). You can configure your endpoints to be either public (no authentication) or to require IAM authentication. With IAM authentication, you can use standard AWS credentials or IAM roles to control access. While straightforward to set up, this approach provides limited options compared with other authenticaton methods.
+ **API Gateway** provides access to a more comprehensive range of authentication options. As well as IAM authentication, you can use [Lambda authorizers](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) (custom authentication logic), [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) user pools, and OAuth2.0 flows. This flexibility allows you to implement complex authentication schemes, including third-party authentication providers, token-based authentication, and multi-factor authentication.

### Request/response handling
<a name="w2aac39c81c73c13c11b3"></a>
+ **Function URLs** provide basic HTTP request and response handling. They support standard HTTP methods and include built-in cross-origin resource sharing (CORS) support. While they can handle JSON payloads and query parameters naturally, they don't offer request transformation or validation capabilities. Response handling is similarly straightforward – the client receives the response from your Lambda function exactly as Lambda returns it.
+ **API Gateway** provides sophisticated request and response handling capabilities. You can define request validators, transform requests and responses using mapping templates, set up request/response headers, and implement response caching. API Gateway also supports binary payloads and custom domain names and can modify responses before they reach the client. You can set up models for request/response validation and transformation using JSON Schema.

### Scaling
<a name="w2aac39c81c73c13c11b5"></a>
+ **Function URLs** scale directly with your Lambda function's concurrency limits and handle traffic spikes by scaling your function up to its maximum configured concurrency limit. Once that limit is reached, Lambda responds to additional requests with HTTP 429 responses. There's no built-in queuing mechanism, so handling scaling is entirely dependent on your Lambda function's configuration. By default, Lambda functions have a limit of 1,000 concurrent executions per AWS Region.
+ **API Gateway** provides additional scaling capabilities on top of Lambda's own scaling. It includes built-in request queuing and throttling controls, allowing you to manage traffic spikes more gracefully. API Gateway can handle up to 10,000 requests per second per region by default, with a burst capacity of 5,000 requests per second. It also provides tools to throttle requests at different levels (API, stage, or method) to protect your backend.

### Monitoring
<a name="w2aac39c81c73c13c11b7"></a>
+ **Function URLs** offer basic monitoring through Amazon CloudWatch metrics, including request count, latency, and error rates. You get access to standard Lambda metrics and logs, which show the raw requests coming into your function. While this provides essential operational visibility, the metrics are focused mainly on function execution.
+ **API Gateway** provides comprehensive monitoring capabilities including detailed metrics, logging, and tracing options. You can monitor API calls, latency, error rates, and cache hit/miss rates through CloudWatch. API Gateway also integrates with AWS X-Ray for distributed tracing and provides customizable logging formats.

### Cost
<a name="w2aac39c81c73c13c11b9"></a>
+ **Function URLs** follow the standard Lambda pricing model – you only pay for function invocations and compute time. There are no additional charges for the URL endpoint itself. This makes it a cost-effective choice for simple APIs or low-traffic applications if you don't need the additional features of API Gateway.
+ **API Gateway** offers a [free tier](https://aws.amazon.com/api-gateway/pricing/#Free_Tier) that includes one million API calls received for REST APIs and one million API calls received for HTTP APIs. After this, API Gateway charges for API calls, data transfer, and caching (if enabled). Refer to the API Gateway [pricing page](https://aws.amazon.com/api-gateway/pricing/) to understand the costs for your own use case.

### Other features
<a name="w2aac39c81c73c13c11c11"></a>
+ **Function URLs** are designed for simplicity and direct Lambda integration. They support both HTTP and HTTPS endpoints, offer built-in CORS support, and provide dual-stack (IPv4 and IPv6) endpoints. While they lack advanced features, they excel in scenarios where you need a quick, straightforward way to expose Lambda functions via HTTP.
+ **API Gateway** includes numerous additional features such as API versioning, stage management, API keys for usage plans, API documentation through Swagger/OpenAPI, WebSocket APIs, private APIs within a VPC, and WAF integration for additional security. It also supports canary deployments, mock integrations for testing, and integration with other AWS services beyond Lambda.

## Select a method to invoke your Lambda function
<a name="w2aac39c81c73c15"></a>

Now that you've read about the criteria for selecting between Lambda function URLs and API Gateway and the key differences between them, you can select the option that best meets your needs and use the following resources to help you get started using it.

------
#### [ Function URLs ]

**Get started with function URLs with the following resources**
+ Follow the tutorial [Creating a Lambda function with a function URL](urls-webhook-tutorial.md)
+ Learn more about function URLs in the [Creating and managing Lambda function URLs](urls-configuration.md) chapter of this guide
+ Try the in-console guided tutorial **Create a simple web app** by doing the following:

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

1. Open the help panel by choosing the icon in the top right corner of the screen.  
![\[\]](http://docs.aws.amazon.com/lambda/latest/dg/images/console_help_screenshot.png)

1. Select **Tutorials**.

1. In **Create a simple web app**, choose **Start tutorial**.

------
#### [ API Gateway ]

**Get started with Lambda and API Gateway with the following resources**
+ Follow the tutorial [Using Lambda with API Gateway](services-apigateway-tutorial.md) to create a REST API integrated with a backend Lambda function.
+ Learn more about the different kinds of API offered by API Gateway in the following sections of the *Amazon API Gateway Developer Guide*:
  + [API Gateway REST APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html)
  + [API Gateway HTTP APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html)
  + [API Gateway WebSocket APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html)
+ Try one or more of the examples in the [Tutorials and workshops](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-tutorials.html) section of the *Amazon API Gateway Developer Guide*.

------

# Tutorial: Creating a webhook endpoint using a Lambda function URL
<a name="urls-webhook-tutorial"></a>

In this tutorial, you create a Lambda function URL to implement a webhook endpoint. A webhook is a lightweight, event-driven communication that automatically sends data between applications using HTTP. You can use a webhook to receive immediate updates about events happening in another system, such as when a new customer signs up on a website, a payment is processed, or a file is uploaded.

With Lambda, webhooks can be implemented using either Lambda function URLs or API Gateway. Function URLs are a good choice for simple webhooks that don't require features like advanced authorization or request validation.

**Tip**  
If you're not sure which solution is best for your particular use case, see [Select a method to invoke your Lambda function using an HTTP request](furls-http-invoke-decision.md).

## Prerequisites
<a name="urls-webhook-tutorial-prereqs"></a>

To complete this tutorial, you must have either Python (version 3.8 or later) or Node.js (version 18 or later) installed on your local machine.

To test the endpoint using an HTTP request, the tutorial uses [curl](https://curl.se/), a command line tool you can use to transfer data using various network protocols. Refer to the [curl documentation](https://curl.se/docs/install.html) to learn how to install the tool if you don't already have it.

## Create the Lambda function
<a name="urls-webhook-tutorial-function"></a>

First create the Lambda function that runs when an HTTP request is sent to your webhook endpoint. In this example, the sending application sends an update whenever a payment is submitted and indicates in the body of the HTTP request whether the payment was successful. The Lambda function parses the request and takes action according to the status of the payment. In this example, the code just prints the order ID for the payment, but in a real application, you might add the order to a database or send a notification.

The function also implements the most common authentication method used for webhooks, hash-based message authentication (HMAC). With this method, both the sending and receiving applications share a secret key. The sending application uses a hashing algorithm to generate a unique signature using this key together with the message content, and includes the signature in the webhook request as an HTTP header. The receiving application then repeats this step, generating the signature using the secret key, and compares the resulting value with the signature sent in the request header. If the result matches, the request is considered legitimate. 

Create the function using the Lambda console with either the Python or Node.js runtime.

------
#### [ Python ]

**Create the Lambda function**

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

1. Create a basic 'Hello world' function by doing the following:

   1. Choose **Create function**.

   1. Select **Author from scratch**.

   1. For **Function name**, enter **myLambdaWebhook**.

   1. For **Runtime**, select **python3.14**.

   1. Choose **Create function**.

1. In the **Code source** pane, replace the existing code by copying and pasting the following:

   ```
   import json
   import hmac
   import hashlib
   import os
   
   def lambda_handler(event, context):
       
       # Get the webhook secret from environment variables
       webhook_secret = os.environ['WEBHOOK_SECRET']
       
       # Verify the webhook signature
       if not verify_signature(event, webhook_secret):
           return {
               'statusCode': 401,
               'body': json.dumps({'error': 'Invalid signature'})
           }
       
       try:
           # Parse the webhook payload
           payload = json.loads(event['body'])
           
           # Handle different event types
           event_type = payload.get('type')
           
           if event_type == 'payment.success':
               # Handle successful payment
               order_id = payload.get('orderId')
               print(f"Processing successful payment for order {order_id}")
               
               # Add your business logic here
               # For example, update database, send notifications, etc.
               
           elif event_type == 'payment.failed':
               # Handle failed payment
               order_id = payload.get('orderId')
               print(f"Processing failed payment for order {order_id}")
               
               # Add your business logic here
               
           else:
               print(f"Received unhandled event type: {event_type}")
           
           # Return success response
           return {
               'statusCode': 200,
               'body': json.dumps({'received': True})
           }
           
       except json.JSONDecodeError:
           return {
               'statusCode': 400,
               'body': json.dumps({'error': 'Invalid JSON payload'})
           }
       except Exception as e:
           print(f"Error processing webhook: {e}")
           return {
               'statusCode': 500,
               'body': json.dumps({'error': 'Internal server error'})
           }
   
   def verify_signature(event, webhook_secret):
       """
       Verify the webhook signature using HMAC
       """
       try:
           # Get the signature from headers
           signature = event['headers'].get('x-webhook-signature')
   
           if not signature:
               print("Error: Missing webhook signature in headers")
               return False
           
           # Get the raw body (return an empty string if the body key doesn't exist)
           body = event.get('body', '')
           
           # Create HMAC using the secret key
           expected_signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
           
           # Compare the expected signature with the received signature to authenticate the message
           is_valid = hmac.compare_digest(signature, expected_signature)
           if not is_valid:
               print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}")
               return False
               
           return True
       except Exception as e:
           print(f"Error verifying signature: {e}")
           return False
   ```

1. In the **DEPLOY** section, choose **Deploy** to update your function's code.

------
#### [ Node.js ]

**Create the Lambda function**

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

1. Create a basic 'Hello world' function by doing the following:

   1. Choose **Create function**.

   1. Select **Author from scratch**.

   1. For **Function name**, enter **myLambdaWebhook**.

   1. For **Runtime**, select **nodejs24.x**.

   1. Choose **Create function**.

1. In the **Code source** pane, replace the existing code by copying and pasting the following:

   ```
   import crypto from 'crypto';
   
   export const handler = async (event, context) => {
       // Get the webhook secret from environment variables
       const webhookSecret = process.env.WEBHOOK_SECRET;
   
       // Verify the webhook signature
       if (!verifySignature(event, webhookSecret)) {
           return {
               statusCode: 401,
               body: JSON.stringify({ error: 'Invalid signature' })
           };
       }
   
       try {
           // Parse the webhook payload
           const payload = JSON.parse(event.body);
   
           // Handle different event types
           const eventType = payload.type;
   
           switch (eventType) {
               case 'payment.success': {
                   // Handle successful payment
                   const orderId = payload.orderId;
                   console.log(`Processing successful payment for order ${orderId}`);
   
                   // Add your business logic here
                   // For example, update database, send notifications, etc.
                   break;
               }
   
               case 'payment.failed': {
                   // Handle failed payment
                   const orderId = payload.orderId;
                   console.log(`Processing failed payment for order ${orderId}`);
   
                   // Add your business logic here
                   break;
               }
   
               default:
                   console.log(`Received unhandled event type: ${eventType}`);
           }
   
           // Return success response
           return {
               statusCode: 200,
               body: JSON.stringify({ received: true })
           };
   
       } catch (error) {
           if (error instanceof SyntaxError) {
               // Handle JSON parsing errors
               return {
                   statusCode: 400,
                   body: JSON.stringify({ error: 'Invalid JSON payload' })
               };
           }
   
           // Handle all other errors
           console.error('Error processing webhook:', error);
           return {
               statusCode: 500,
               body: JSON.stringify({ error: 'Internal server error' })
           };
       }
   };
   
   // Verify the webhook signature using HMAC
   
   const verifySignature = (event, webhookSecret) => {
       try {
           // Get the signature from headers
           const signature = event.headers['x-webhook-signature'];
     
           if (!signature) {
               console.log('No signature found in headers:', event.headers);
               return false;
           }
     
           // Get the raw body (return an empty string if the body key doesn't exist)
           const body = event.body || '';
     
           // Create HMAC using the secret key
           const hmac = crypto.createHmac('sha256', webhookSecret);
           const expectedSignature = hmac.update(body).digest('hex');
     
           // Compare expected and received signatures
           const isValid = signature === expectedSignature;
           if (!isValid) {
               console.log(`Invalid signature. Received: ${signature}, Expected: ${expectedSignature}`);
               return false;
           }
           
           return true;
       } catch (error) {
           console.error('Error during signature verification:', error);
           return false;
       }
     };
   ```

1. In the **DEPLOY** section, choose **Deploy** to update your function's code.

------

## Create the secret key
<a name="urls-webhook-tutorial-key"></a>

For the Lambda function to authenticate the webhook request, it uses a secret key which it shares with the calling application. In this example, the key is stored in an environment variable. In a production application, don't include sensitive information like passwords in your function code. Instead, [create an AWS Secrets Manager secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) and then [use the AWS Parameters and Secrets Lambda extension](with-secrets-manager.md) to retrieve your credentials in your Lambda function.

**Create and store the webhook secret key**

1. Generate a long, random string using a cryptographically secure random number generator. You can use the following code snippets in Python or Node.js to generate and print a 32-character secret, or use your own preferred method.

------
#### [ Python ]

**Example code to generate a secret**  

   ```
   import secrets
   webhook_secret = secrets.token_urlsafe(32)
   print(webhook_secret)
   ```

------
#### [ Node.js ]

**Example code to generate a secret (ES module format)**  

   ```
   import crypto from 'crypto';
   let webhookSecret = crypto.randomBytes(32).toString('base64');
   console.log(webhookSecret)
   ```

------

1. Store your generated string as an environment variable for your function by doing the following:

   1. In the **Configuration** tab for your function, select **Environment variables**.

   1. Choose **Edit**.

   1. Choose **Add environment variable**.

   1. For **Key**, enter **WEBHOOK\$1SECRET**, then for **Value**, enter the secret you generated in the previous step.

   1. Choose **Save**.

You'll need to use this secret again later in the tutorial to test your function, so make a note of it now.

## Create the function URL endpoint
<a name="urls-webhook-tutorial-furl"></a>

Create an endpoint for your webhook using a Lambda function URL. Beacuse you use the auth type of `NONE` to create an endpoint with public access, anyone with the URL can invoke your function. To learn more about controlling access to function URLs, see [Control access to Lambda function URLs](urls-auth.md). If you need more advanced authentication options for your webhook, consider using API Gateway.

**Create the function URL endpoint**

1. In the **Configuration** tab for your function, select **Function URL**.

1. Choose **Create function URL**.

1. For **Auth type**, select **NONE**.

1. Choose **Save**.

The endpoint for the function URL you just created is displayed in the **Function URL** pane. Copy the endpoint to use later in the tutorial.

## Test the function in the console
<a name="urls-webhook-tutorial-test-console"></a>

Before using an HTTP request to invoke your function using the URL endpoint, test it in the console to confirm your code is working as expected.

To verify the function in the console, you first calculate a webhook signature using the secret you generated earlier in the tutorial with the following test JSON payload:

```
{
    "type": "payment.success", 
    "orderId": "1234",
    "amount": "99.99"
}
```

Use either of the following Python or Node.js code examples to calculate the webhook signature using your own secret.

------
#### [ Python ]

**Calculate the webhook signature**

1. Save the following code as a file named `calculate_signature.py`. Replace the webhook secret in the code with your own value.

   ```
   import secrets
   import hmac
   import json
   import hashlib
   
   webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   
   body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"})
   
   signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
   
   print(signature)
   ```

1. Calculate the signature by running the following command from the same directory you saved the code in. Copy the signature the code outputs.

   ```
   python calculate_signature.py
   ```

------
#### [ Node.js ]

**Calculate the webhook signature**

1. Save the following code as a file named `calculate_signature.mjs`. Replace the webhook secret in the code with your own value.

   ```
   import crypto from 'crypto';
   
   const webhookSecret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   const body = "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}";
   
   let hmac = crypto.createHmac('sha256', webhookSecret);
   let signature = hmac.update(body).digest('hex');
   
   console.log(signature);
   ```

1. Calculate the signature by running the following command from the same directory you saved the code in. Copy the signature the code outputs.

   ```
   node calculate_signature.mjs
   ```

------

You can now test your function code using a test HTTP request in the console.

**Test the function in the console**

1. Select the **Code** tab for your function.

1. In the **TEST EVENTS** section, choose **Create new test event**

1. For **Event Name**, enter **myEvent**.

1. Replace the existing JSON by copying and pasting the following into the **Event JSON** pane. Replace the webhook signature with the value you calculated in the previous step.

   ```
   {
     "headers": {
       "Content-Type": "application/json",
       "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a"
     },
     "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}"
   }
   ```

1. Choose **Save**.

1. Choose **Invoke**.

   You should see output similar to the following:

------
#### [ Python ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\": true}"
   }
   
   Function Logs:
   START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST
   Processing successful payment for order 1234
   END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6
   REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6	Duration: 1.55 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 136.32 ms
   ```

------
#### [ Node.js ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\":true}"
   }
   
   Function Logs:
   START RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Version: $LATEST
   2025-01-10T18:05:42.062Z	e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	INFO	Processing successful payment for order 1234
   END RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   REPORT RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	Duration: 60.10 ms	Billed Duration: 61 ms	Memory Size: 128 MB	Max Memory Used: 72 MB	Init Duration: 174.46 ms
   
   Request ID: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   ```

------

## Test the function using an HTTP request
<a name="urls-webhook-tutorial-test-curl"></a>

Use the curl command line tool to test your webhook endpoint.

**Test the function using HTTP requests**

1. In a terminal or shell program, run the following curl command. Replace the URL with the value for your own function URL endpoint and replace the webhook signature with the signature you calculated using your own secret key.

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   You should see the following output:

   ```
   {"received": true}
   ```

1. Inspect the CloudWatch logs for your function to confirm it parsed the payload correctly by doing the following:

   1. Open the [Logs group](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) page in the Amazon CloudWatch console.

   1. Select your function's log group (`/aws/lambda/myLambdaWebhook`).

   1. Select the most recent log stream.

      You should see output similar to the following in your function's logs:

------
#### [ Python ]

      ```
      Processing successful payment for order 1234
      ```

------
#### [ Node.js ]

      ```
      2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234
      ```

------

1. Confirm that your code detects an invalid signature by running the following curl command. Replace the URL with your own function URL endpoint.

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: abcdefg" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   You should see the following output:

   ```
   {"error": "Invalid signature"}
   ```

## Clean up your resources
<a name="urls-webhook-tutorial-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 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**.

When you created the Lambda function in the console, Lambda also created an [execution role](lambda-intro-execution-role.md) for your function.

**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 Lambda created. The role has the name format `myLambdaWebhook-role-<random string>`.

1. Choose **Delete**.

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