AWS Compute Blog
AWS Lambda introduces recursive loop detection APIs
This post is written by James Ngai, Senior Product Manager, AWS Lambda, and Aneel Murari, Senior Specialist SA, Serverless.
Today, AWS Lambda is announcing new recursive loop detection APIs that allow you to set recursive loop detection configuration on individual Lambda functions. This allows you to turn off recursive loop detection on functions that intentionally use recursive patterns, avoiding disruption of these workloads. You can use these APIs to avoid disruption to any intentionally recursive workflows as Lambda expands support of recursive loop detection to other AWS services.
Overview
AWS Lambda functions are triggered in response to events generated by various AWS services. These Lambda functions may interact with other AWS services by invoking the corresponding service APIs. Typically, the service and resource that generates the triggering event is distinct from the service and resource that the Lambda function calls. However, due to coding errors or configuration issues, there may be situations where these two resources are the same, leading to an infinite or recursive loop. Such misconfigurations can result in runaway workloads, which can incur unplanned usage and charges to your AWS account. For example, a Lambda function processes messages from an Amazon Simple Notification Service (SNS) topic but then puts the resulting notification back to the same SNS topic. This causes an infinite loop.
Lambda provides a built-in preventative guardrail that detects and stops functions running in a recursive or infinite loop between Lambda, Amazon Simple Queue Service (SQS), and SNS. This feature, known as recursive loop detection, is enabled by default for all Lambda functions. This serves as a protective mechanism against unintended usage and unexpected billing from runaway workloads.
Lambda uses an AWS X-Ray trace header primitive called “lineage” to track the number of times a function has been invoked with an event. When your function code sends an event using a supported AWS SDK version, Lambda increments the counter in the lineage header. If your function is then invoked with the same triggering event more than 16 times, Lambda stops the next invocation for that event and emits an Amazon CloudWatch RecursiveInvocationsDropped
metric. If the function is invoked synchronously, Lambda returns a RecursiveInvocationException
to the caller. For asynchronous invocations, Lambda sends the event to a dead-letter queue or on-failure destination if one is configured.
You do not need to configure active X-Ray tracing for this feature to work. For more information on this feature and an example scenario, please refer to Detecting and stopping recursive loops in AWS Lambda functions.
Although AWS generally discourages this practice due to the possibility of runaway workloads, some customers intentionally employ recursive patterns in their workflows. Previously, customers that run workloads that intentionally use recursive patterns could only opt-out of recursive loop detection on a per-account basis by contacting AWS Support. With these new APIs, customers can selectively opt-out of recursive loop detection on individual functions while maintaining this preventative guardrail for the remaining functions in their account that do not use recursive code.
Today we are introducing two new API actions for recursive loop detection:
GetFunctionRecursionConfig
returns details about a function’s recursive loop detection configuration.PutFunctionRecursionConfig
sets the recursive loop detection configuration for a function. By default, recursive loop detection is turned ON for all functions.
How to use the new recursive loop detection APIs
You can configure recursive loop detection for Lambda functions through the Lambda Console, the AWS CLI, or Infrastructure as Code tools like AWS CloudFormation, AWS Serverless Application Model (AWS SAM), or AWS Cloud Development Kit (CDK). This new configuration option is supported in AWS SAM CLI version 1.123.0 and CDK v2.153.0.
If you turn recursive loop detection off for a function, the metric for RecursiveInvocationsDropped
is no longer emitted for that function.
Turning off recursive loop detection on your function means that Lambda no longer prevents recursive invocations caused by misconfiguration. This may lead to unexpected usage and billing to your AWS account. You should explore alternate ways of architecting your workload that do not use recursive patterns. AWS recommends you exercise caution when turning off this guardrail feature.
Setting recursive loop detection configuration on a function using the Lambda Console
You can get recursive loop detection configuration in the AWS Lambda console:
- In the AWS Lambda Console, navigate to the Functions page. Select the function that uses intentionally recursive patterns.
- Select Configuration. You can find recursive loop detection controls under the Concurrency and recursion detection section.
- Recursive loop detection is turned on by default for all functions. You can change the recursive loop detection configuration of a function by choosing Edit.
- To turn off recursive loop detection for a function, select Allow recursive loops and select Save.
Setting recursive loop detection configuration using the AWS CLI
You can get the current recursion loop detection configuration of a Lambda function by using the following CLI command:
aws lambda get-function-recursion-config \
--region $AWS_REGION \
--function-name $FUNCTION_NAME
You can update the recursion loop detection configuration for a Lambda function by using the following CLI command:
aws lambda put-function-recursion-config \
--region $AWS_REGION \
--function-name $FUNCTION_NAME \
--recursive-loop Allow|Terminate
Make sure to set appropriate values for AWS_REGION
and FUNCTION_NAME
in the previous commands. Setting the put-function-recursion-config parameter to Allow turns off the default behavior of detecting recursive loops. Set this value to Terminate to switch back to default behavior.
Setting recursive loop detection configuration using AWS CloudFormation
You can control the recursive loop detection configuration for a Lambda function by setting the RecursiveLoop
resource property in CloudFormation. Setting the value of this property to Allow turns off the default behavior of automatically detecting recursive loops. Set this property to Terminate
if you want to switch it back to the default behavior. The following CloudFormation snippet shows RecursiveLoop
set to Allow
.
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket:S3_BUCKET
S3Key: S3_KEY
Handler: com.example.App::handleRequest
MemorySize: 1024
Role:
Fn::GetAtt:
- LambdaFunctionRole
- Arn
Runtime: java17
RecursiveLoop : Allow
Timeout: 20
TracingConfig:
Mode: Active
Extending recursive loop detection to additional AWS services
Today, recursive loop detection detects and stops loops between Lambda, SQS, and SNS after approximately 16 invocations. Lambda plans to extend support for recursive loop detection to additional AWS services. Using the APIs, you can turn off recursive loop detection for specific functions that use recursive patterns so that they are not impacted when Lambda expands recursive loop detection to additional AWS services in the future.
One way you can identify functions that use recursive patterns is by using the CloudWatch metric RecursiveInvocationsDropped
.
- Set a CloudWatch alarm on all Lambda functions for the CloudWatch metric
RecursiveInvocationsDropped
. Configure the alarm to trigger when the metric is greater than a threshold of zero. Refer to CloudWatch documentation to set alarms. You can use the following CLI command to set this alarm: - When Lambda detects recursive invocations, it will emit the
RecursiveInvocationsDropped
metric, which will trigger the alarm. Note that Lambda will only detect and stop recursive invocations if all the services within the loop support recursive loop detection. - Navigate to the CloudWatch Console and determine which function has emitted the
RecursiveInvocationsDropped
metric. On the Browse tab, under Metrics, choose to view metrics By Function Name and search forRecursiveInvocationsDropped
. This will list all functions that have emitted that metric. - Determine if recursion is the intended pattern for that function. If so, use the recursive loop detection API to turn off recursive loop detection for this function.
aws cloudwatch put-metric-alarm --alarm-name lambda-recursive-alarm --metric-name RecursiveInvocationsDropped --namespace AWS/Lambda --statistic Sum --period 60 --threshold 0 --comparison-operator GreaterThanOrEqualToThreshold --evaluation-periods 1 --alarm-actions $arn-of-sns-notification-topic
Conclusion
Lambda recursive loop detection automatically detects and stops recursive invocations between Lambda and supported services, preventing runaway workloads. In most cases, you should architect your workloads to avoid any recursive loops. In rare and special circumstances, you may want to turn off the default behavior on a case-by-case basis. The recursive loop detection APIs allow you to set recursive loop detection configuration on individual functions.
This feature is available in all AWS Regions where Lambda supports recursive loop detection.
To learn more about these APIs, refer to the AWS Lambda API Reference.
For more serverless learning resources, visit Serverless Land