AWS Lambda - How to stop retries when there is a failure

33,864

Solution 1

EDITED: It's now possible to change the lambda settings to disable retries (see announcement)


Original answer:

There isn't a way to disable retry behavior of Lambda functions. I suggest two options to deal with that:

  1. Make your Lambda able to handle retry cases correctly. You can use context.AwsRequestId (or corresponding field) that will be the same when a Lambda is retried.
  2. Put your Lambda inside a state machine (using AWS Step Functions). You can only then disable retries. This blog post I've written gives a more general explanation.

Solution 2

It retries when it is an unhandled failure (an error that you didn't catch) or if you handled it but still told Lambda to retry (e.g. in Node, when you call callback() with a non-null first argument).

To stop it from retrying, you should make sure that any error is handled and you tell Lambda that your invocation finished successfully by returning a non-error (or in Node, calling callback(null, <any>).

To do this you can enclose the entire body of your handler function with a try-catch.

module.exports.handler(event, context, callback) {
  try {
    // Do you what you want to do.
    return callback(null, 'Success')
  } catch (err) {
    // You probably still want to log it.
    console.error(err)
    // Return happy despite all the hardships you went through.
    return callback(null, 'Still success')
  }
}

As for failures due to timeouts there are things you can do.

If it times out outside of your handler, there's usually something wrong with your code (e.g. incorrect database config, etc) that you should look at.

If it times out inside your handler during an invocation, there is something you can do about it.

  • If it's an HTTP request, you should set the timeout of the request to be shorter than your Lambda's timeout, this way it will fail properly and you can catch it.
  • If it's a database connection, you can probably set a timeout using the library that you're using.
  • If it's your logic that times out, you can upgrade the Lambda to use higher memory-CPU to make it faster. You can also check context.getRemainingTimeInMillis() to know if the Lambda is about to timeout, so you can handle it earlier.

Solution 3

If you call the function asynchronously, in the Console, under Function configuration, you can modify the Retry attempts:

enter image description here

Solution 4

Since November 2019, it is possible to set the retry count to 0.

That means the lambda will not be retried on error.

Solution 5

As mentioned before, this feature has been added lately. To achieve this behaviour using cloudformation you will need both an AWS::Lambda::Version and AWS::Lambda::EventInvokeConfig:

  MyLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: my-lambda-dev
      ...

  MyLambdaVersion:
    Type: AWS::Lambda::Version
    Properties:
      FunctionName: !Ref MyLambda

  MyLambdaAsyncConfig:
    Type: AWS::Lambda::EventInvokeConfig
    Properties:
      FunctionName: !Ref MyLambda
      MaximumRetryAttempts: 0
      Qualifier: !GetAtt MyLambdaVersion.Version
Share:
33,864
AleGallagher
Author by

AleGallagher

Updated on July 09, 2022

Comments

  • AleGallagher
    AleGallagher almost 2 years

    I know that when a Lambda function fails (for example when there is a time out), it tries to run the function 3 more times again. Is there any way to avoid this behavior? I' have been reading the documentation, but didn't find anyting about this.

    Thanks!

  • AleGallagher
    AleGallagher about 6 years
    Thanks for answering @dashmug! In case of time out error, is it catched in the try catch too? Because it is a limitation of AWS Lamda. Thanks!
  • Noel Llevares
    Noel Llevares about 6 years
    Unfortunately, timeout errors can't be caught by this try-catch.
  • johnny
    johnny over 5 years
    What is the logic that AWS is not changing this behavior it or not making is configurable and can be disabled? Besides making extra money. lol
  • johnny
    johnny over 5 years
    Other option would push the requestid to dynamodb and then check against that if it is a retry or a new invocation. Again more money for AWS. lol
  • grabantot
    grabantot over 5 years
    @dashmug The code within try-catch executes ~5 times slower (js). Still more money for AWS))
  • Castro Roy
    Castro Roy almost 5 years
    Doing this will prevent you from using the CloudWatch Metric for AWS/Lambda Errors. If you are ok with that, then go for it.
  • Renato Byrro
    Renato Byrro almost 5 years
    Is it guaranteed that the retry will hit the same container as the previously failed invocation? Because, if not, this logic is doomed to fail... It's safer to push the request ID to external storage, such as DynamoDB.
  • Renato Byrro
    Renato Byrro almost 5 years
    Actually, this is absolutely certain to fail. Lambda may retry multiple times, with a period of time between each retry. In the meanwhile, Lambda is likely to be invoked by another request, updating the lastReqId. When the retry comes in, you can't identify it anymore.
  • Kshitiz Jaiswal
    Kshitiz Jaiswal almost 5 years
    I tried a poc on streams and this worked, based on my analysis if its stream you are working on and lambda fails it will re-try the failed request and will not take another request. However i see that you have a valid point, As the above might fail in another cases
  • titus
    titus about 4 years
    How can one disable retries if Lambda is invoked from StepFucntions? I have a Lambda Step that retries.
  • Chandan Kumar
    Chandan Kumar almost 4 years
    Isnt it an option to put the context.succeed() in catch block?