6

My use case is such that I'll have an AWS Lambda front ended with API Gateway.

My requirement is that once the Lambda is invoked it should return a 200 OK response back to API Gateway which get forwards this to the caller. And then the Lambda should start its actual processing of the payload.

The reason for this is that the API Gateway caller service expects a response within 10 seconds else it times out. So I want to give the response before I start with the processing.

Is this possible?

1
  • It seems like we've had this question before, but I didn't find an appropriate duplicate question. Commented Dec 12, 2016 at 17:11

4 Answers 4

6

With API Gateway's "Lambda Function" integration type, you can't do this with a single Lambda function -- that interface is specifically designed to be synchronous. The workaround, if you want to use the Lambda Function integration type is for the synchronous Lambda function, invoked by the gateway, to invoke a second, asynchronous, Lambda function through the Lambda API.

However, asynchronous invocations are possible without the workaround, using an AWS Service Proxy integration instead of a Lambda Function integration.

If your API makes only synchronous calls to Lambda functions in the back end, you should use the Lambda Function integration type. [...]

If your API makes asynchronous calls to Lambda functions, you must use the AWS Service Proxy integration type described in this section. The instructions apply to requests for synchronous Lambda function invocations as well. For the asynchronous invocation, you must explicitly add the X-Amz-Invocation-Type:Event header to the integration request.

http://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html

Sign up to request clarification or add additional context in comments.

3 Comments

How do we add this header? do we have to add it under "HTTP Header"? in Integration Request? It seems like I can only add header mapping, but not a hardcoded header value. Thanks.
Ok, It's allowing header value in single quotes, but not double quotes. That's where I was struggling. Such a bad UX.
@vangap 'STATIC_VALUE'. "The STATIC_VALUE is a string literal and must be enclosed within a pair of single quotes." docs.aws.amazon.com/apigateway/latest/developerguide/…
3

Yes, simply create two Lambda functions. The first Lambda function will be called by the API Gateway and will simply invoke the second Lambda function and then immediately return successfully so that the API Gateway can respond with an HTTP 200 to the client. The second Lambda function will then take as long as long as it needs to complete.

2 Comments

Alternatively, a queue (SQS) can be used. You can connect the API Gateway directly to a SQS-queue or use a Lambda function. In any case, you can process messages in a pace you prefer.
Yes 2 lambda approach can definitely be done. But can we have that with a single lambda
2

If anyone is interested, here is the code you can use to do the two lambdas approach. The code below is the first lambda that you should setup which would then call the second, longer running, lambda. It takes well under a second to execute.

const Lambda = new (require('aws-sdk')).Lambda();

/**
 * Note: Step Functions, which are called out in many answers online, do NOT actually work in this case.  The reason
 * being that if you use Sequential or even Parallel steps they both require everything to complete before a response
 * is sent.  That means that this one will execute quickly but Step Functions will still wait on the other one to
 * complete, thus defeating the purpose.
 *
 * @param {Object} event The Event from Lambda
 */
exports.handler = async (event) => {
    let params = {
      FunctionName: "<YOUR FUNCTION NAME OR ARN>",
      InvocationType: "Event",  // <--- This is KEY as it tells Lambda to start execution but immediately return / not wait.
      Payload: JSON.stringify( event )
    };

    // we have to wait for it to at least be submitted. Otherwise Lambda runs too fast and will return before
    // the Lambda can be submitted to the backend queue for execution
    await new Promise((resolve, reject) => {
        Lambda.invoke(params, function(err, data) {
            if (err) {
                reject(err, err.stack);
            }
            else {
                resolve('Lambda invoked: '+data) ;
            }
        });
    });

    // Always return 200 not matter what
    return {
        statusCode : 200,
        body: "Event Handled"
    };

};

Comments

1

Check the answer here on how to set up an Async Invoke to the Lambda function. This will return 200 immediately to the client, but the Lambda will process on it's own asynchronously.

https://stackoverflow.com/a/40982649/5679071

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.