Mukesh S
Mukesh S

Reputation: 377

AWS Cognito lambda triggers twice

I'm using an AWS Lambda function (using nodejs).

Once any request from APP to Cognito to signUp users. Then I have set the Pre sign-up trigger to validate the user's customer and check users custom attribute available in our database or not. If yes then return an error and else insert new records in DB and return the event to Cognito.

TimeoutInfo - 5 min.

It happens sometime in the request, not all the time. RequestId as different. (it will trigger 3 times sometime and most of the time twice)

Lambda trigger code as below.

users/index.js

const handler = async (event, context) => {
  log.info('createUserLambda:start');
  // immediately return once the call back is called to avoid
  // lambda time out because of any open db connections
  context.callbackWaitsForEmptyEventLoop = false;
  return await preUserCreate(event);
};

exports.handler = handler; users/users.js

export const preUserCreate = async (event) => {
  log.info('preUserCreate:Start');
  let userAttributes = event.request.userAttributes;
  const currentDate = moment().utc().format('YYYY-MM-DD HH:mm:ss');
  try {
    let userParams = {
      'docStatus': 'VRF'
    };
    let docParams = [{
      'docNumber': userAttributes['custom:document_number'] ? userAttributes['custom:document_number'] : '',
      'createdDate': currentDate
    }];
    if (docParams.length && docParams[0].docNumber) {
      let documentExit = await getDocs(docParams[0].docNumber);
      if (documentExit.length) {
        log.info('preUserCreate:Error');
        throw new Error('Document number already exist.');;
      }
    }

    let documentRs = await insertDocument(docParams);
    userParams = {
      'did': documentRs[0].id,
      'id': event.userName,
      'createdDate': currentDate,
      'updatedDate': currentDate,
      ...userParams
    };
    let userRs = await insertUser([userParams]);
    if (docParams.length && docParams[0].docNumber) {
      let resultData = await getUserAccountFromAPI(docParams[0].docNumber);
      if (resultData) {
        let foramattedData = await formattedAccountsData(resultData, userRs[0].id, documentRs[0].id);
        await insertUserAccounts(foramattedData);
      }
    }
    log.info('preUserCreate:Success');
    event.response = {
      'autoConfirmUser': false,
      'autoVerifyPhone': false,
      'autoVerifyEmail': false
    };
    return event;
  } catch (error) {
    log.info('preUserCreate:Error', error);
    throw (error);
  }
}

Upvotes: 10

Views: 4852

Answers (2)

M Jensen
M Jensen

Reputation: 566

This likely happens because of the Cognito-imposed execution timeout of 5 seconds for integration Lambdas - and it cannot be changed. Also note that the maximum amount of times that Cognito will (re-)attempt to call the function is 3 times.

In the Customizing User Pool Workflows with Lambda Triggers section it states that:

Important Amazon Cognito invokes Lambda functions synchronously. When called, your Lambda function must respond within 5 seconds. If it does not, Amazon Cognito retries the call. After 3 unsuccessful attempts, the function times out. This 5-second timeout value cannot be changed.

Therefore to reduce the execution time it would be worth to consider introducing caching where possible. Including database connections etc.

Do however note that you have little to no control over how often Lambdas are re-used versus re-launched and you will need to keep this in mind in terms of warm-up times.

Upvotes: 15

Brian Winant
Brian Winant

Reputation: 3035

Any chance you are running your lambda in a VPC? I've seen similar behavior with a Cognito trigger that ran in a VPC when it was cold started. Once the lambda was warm the problem went away

My hunch was that internally Cognito has a very short timeout period for executing the trigger, and if the trigger didn't reply in time, it would automatically retry.

We ended up having to add logic to our trigger to test for this scenario so that we weren't duplicating writes to our database.

Upvotes: 5

Related Questions