Use Lambda recursive loop detection to prevent infinite loops
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 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 for more information.
Sections
Understanding recursive loop detection
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 tracing headers. When AWS services that support recursive loop detection 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, 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 or dead-letter queue 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 Amazon SNS topic or Amazon SQS queue that your function also uses as an event trigger or event source mapping. If you send events to the same resource that invokes your function, then you can create another recursive loop.
Supported AWS services and SDKs
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
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:
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 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 to notify you when spending in your account exceeds a threshold that you specify. Or, you can use AWS Cost Anomaly Detection to alert you to unusual billing patterns.
Supported AWS SDKs
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 |
SDK V2 (use latest version) |
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. For a list of the SDKs included with each Lambda runtime, see Lambda runtimes.
Recursive loop notifications
When Lambda stops a recursive loop, you receive notifications through the AWS Health Dashboard
AWS Health Dashboard notifications
When Lambda stops a recursive invocation, the AWS Health Dashboard displays a notification on the Your account health page,
under Open and recent issues
Email alerts
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 three 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 in the AWS General Reference.
Amazon CloudWatch metrics
The CloudWatch metric
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 and choose the metric RecursiveInvocationsDropped
.
Responding to recursive loop detection notifications
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 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 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, not for event source queues.
If the event source is an Amazon SNS topic, then consider adding an on-failure destination for your function.
To reduce your function's available concurrency to zero (console)
Open the Functions page
of the Lambda console. -
Choose the name of your function.
-
Choose Throttle.
-
In the Throttle your function dialog box, choose Confirm.
To remove a trigger or event source mapping for your function (console)
Open the Functions page
of the Lambda console. -
Choose the name of your function.
-
Choose the Configuration tab, then choose Triggers.
-
Under Triggers, select the trigger or event source mapping that you want to delete, then choose Delete.
-
In the Delete triggers dialog box, choose Delete.
To disable an event source mapping for your function (AWS CLI)
-
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
command. aws lambda list-event-source-mappings
-
To disable the event source mapping, run the following AWS CLI update-event-source-mapping
command. aws lambda update-event-source-mapping --function-name
MyFunction
\ --uuida1b2c3d4-5678-90ab-cdef-EXAMPLE11111
--no-enabled
Allowing a Lambda function to run in a recursive loop
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
You can configure functions to allow recursive loops using the Lambda console, the AWS Command Line Interface (AWS CLI), and the PutFunctionRecursionConfig API. You can also configure a function's recursive loop detection setting in AWS SAM and AWS 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 RecursiveInvocationsDropped
isn't emitted.
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.
Supported regions for Lambda recursive loop detection
Lambda recursive loop detection is supported in the following AWS Regions.
-
US East (N. Virginia)
-
US East (Ohio)
-
US West (N. California)
-
US West (Oregon)
-
Africa (Cape Town)
-
Asia Pacific (Hong Kong)
-
Asia Pacific (Jakarta)
-
Asia Pacific (Mumbai)
-
Asia Pacific (Osaka)
-
Asia Pacific (Seoul)
-
Asia Pacific (Singapore)
-
Asia Pacific (Sydney)
-
Asia Pacific (Tokyo)
-
Canada (Central)
-
Europe (Frankfurt)
-
Europe (Ireland)
-
Europe (London)
-
Europe (Milan)
-
Europe (Paris)
-
Europe (Stockholm)
-
Middle East (Bahrain)
-
South America (Sao Paulo)