Reputation: 25147
The very first time I login to my application, first thing in the morning, AWS Cognito returns this error:
{
"message": "arn:aws:lambda:us-east-1:XXXXXXXXXX:function:main-devryan-users_onCognitoLogin failed with error Socket timeout while invoking Lambda function.",
"code": "UnexpectedLambdaException",
"time": "2017-08-29T13:30:01.351Z",
"requestId": "1c04c982-8cbe-11e7-b9c9-a584e55a17f8",
"statusCode": 400,
"retryable": false,
"retryDelay": 96.636396268355
}
The second time, and every time afterwards for the rest of the day, everything is fine.
When I check the logs in Cloudwatch for my main-devryan-users_onCognitoLogin function, it finished successfully in 2.3 seconds:
REPORT RequestId: 1f2d5a22-8cbe-11e7-ba74-5b21665a40c1 Duration: 2283.60 ms Billed Duration: 2300 ms Memory Size: 128 MB Max Memory Used: 51 MB
Every time afterwards, for the rest of the day, I don't see this error. My Lambda is set to timeout after 30 seconds, but I know Cognito needs a response in 5 seconds.
My lambda function is just updating the last login time in the DB. It's slow the first time because it takes about 1.8 seconds to create a connection to my RDS DB. I'm using Node JS 6 with Sequelize 3 for that part.
I'm guessing it took 2.7 seconds for Lambda to load my app into a container.
Does anybody have solution here? I'm stumped.
Upvotes: 7
Views: 7919
Reputation: 25147
I solved this problem by creating 2 Lambdas: onLogin
and actualOnLogin
. The onLogin
Lambda just kicks off the actualOnLogin
Lambda asynchronously and returns immediately. The actualOnLogin
does my database update. This way onLogin
returns in <100ms and Cognito is happy.
Here's the basic code for onLogin:
let AWS = require("aws-sdk");
let lambda = new AWS.Lambda();
let params = {
FunctionName: "main-@deploy_env@-users_actualCognitoLogin", // I'm using the Serverless framework
InvocationType: "Event", // Makes it async
LogType: "None",
Payload: JSON.stringify(event)
};
lambda.invoke(params, (err, data) => {
if (err) {
console.log("ERROR: " + err, err.stack); // an error occurred
context.done(err, event);
} else {
console.log(data); // successful response
context.done(null, event);
}
});
Upvotes: 3
Reputation: 5751
This seems to be a lambda cold start time issue. There are various approaches you can try to optimize this such as:
Increase the memory allocated to your functions, which also increases CPU proportionally. Because your functions are called very infrequently, the added cost of increasing memory size will be balanced by faster cold start times and thus lower billed duration.
Reduce your code size: a smaller .zip, removing unnecessary require()'s in Node.js, etc. For example, if you are including the Async library just to remove a nested callback, consider forgoing that to improve performance.
Upvotes: 6