AWS Lambda
functions are everywhere. We are using it for various use cases. Sometimes we want to invoke Lambda functions over HTTP
and other times trigger
a function based on some external events. It is extremely useful to understand the different ways we can invoke Lambda functions. Here are 3 different ways we can invoke AWS Lambda function:
Synchronous Invokes
This is the simplest lambda invocation model. When we perform a Lambda invoke an API call, we wait for the function to process the event and return a response or times out. The response includes the function response and additional data.
To perform synchronous invocation we can use the CLI or any of the supported SDKs.
Example of synchronous invoke using the CLI:
aws lambda invoke —function-name MyLambdaFunction —invocation-type RequestResponse —payload '{ "key": "value" }'
Example of synchronous invoke using the Node.js SDK:
const AWS = require("aws-sdk");
const lambda = new AWS.Lambda();
const params = {
FunctionName: "MyLambdaFunction",
InvocationType: "RequestResponse",
Payload: JSON.stringify({ key: "value" })
};
await lambda.invoke(params).promise();
When we specify the
Invocation-type
flag orInvocationType
parameter value asRequestResponse
it instructs AWS to execute our function and wait for the function to complete. One of the drawbacks of synchronous invoke is we are responsible for checking the response and determining whether it is an error and we should retry the invoke.
There are many AWS services that can trigger lambda function synchronously. Here are some of them:
- ELB (Application Load Balancer)
- Cognito
- Lex
- Alexa
- API Gateway
- CloudFront (Lambda@Edge)
- Kinesis Data Firehose
Asynchronous Invokes
When we invoke a function asynchronously, Lambda sends the event to a queue and returns a success response without additional information. A separate process reads events from the queue and runs our function. To invoke a function asynchronously, we have to set the invocation type parameter to Event.
Example of an asynchronous invokes using the CLI:
aws lambda invoke —function-name MyLambdaFunction —invocation-type Event —payload '{ "key": "value" }'
Example of an asynchronous invokes using the Node.js SDK:
const AWS = require("aws-sdk");
const lambda = new AWS.Lambda();
const params = {
FunctionName: "MyLambdaFunction",
InvokeArgs: JSON.stringify({
Records: [
{
eventVersion: "2.0",
eventSource: "aws:s3",
awsRegion: "us-west-2",
eventTime: "1970-01-01T00:00:00.000Z",
eventName: "ObjectCreated:Put",
userIdentity: {
principalId: "AIDAJDPLRKLG7UEXAMPLE"
},
requestParameters: {
sourceIPAddress: "127.0.0.1"
},
responseElements: {
"x-amz-request-id": "C3D13FE58DE4C810",
"x-amz-id-2":
"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
s3: {
s3SchemaVersion: "1.0",
configurationId: "testConfigRule",
bucket: {
name: "sourcebucket",
ownerIdentity: {
principalId: "A3NL1KOZZKExample"
},
arn: "arn:aws:s3:::sourcebucket"
},
object: {
key: "HappyFace.jpg",
size: 1024,
eTag: "d41d8cd98f00b204e9800998ecf8427e",
versionId: "096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
})
};
await lambda.invokeAsync(params).promise();
You can use the above code snippet to write integration tests for your lambda function that gets trigger based on the s3 event.
When we specify the
Invocation-type
flag orInvocationType
parameter value asEvent
if the function failed AWS will automatically retry the invoke twice.
Here is a list of services that invoke Lambda functions asynchronously:
- S3
- SNS
- SES
- CloudFormation
- CloudWatch Logs
- CloudWatch Events
- CodeCommit
Pool Based Invokes
Pool-Based invocation model allows us to integrate with AWS Stream and Queue based services. Lambda will poll records from services (Kinesis, SQS, DynamoDB Streams
) and invoke our functions. AWS Lambda Event Source Mapping manages the poller and performs Synchronous invokes of our function.
Here is an example mapping of a function (MyLambdaFunction
) to a Kinesis stream (arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream
) with a batch size of 500:
$ aws lambda create-event-source-mapping --function-name MyLambdaFunction \
--batch-size 500 --starting-position AT_TIMESTAMP --starting-position-timestamp 1541139109 \
--event-source-arn arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream
{
"UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
"BatchSize": 500,
"MaximumBatchingWindowInSeconds": 0,
"ParallelizationFactor": 1,
"EventSourceArn": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream",
"FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:MyLambdaFunction",
"LastModified": 1541139209.351,
"LastProcessingResult": "No records processed",
"State": "Creating",
"StateTransitionReason": "User action",
"DestinationConfig": {},
"MaximumRecordAgeInSeconds": 604800,
"BisectBatchOnFunctionError": false,
"MaximumRetryAttempts": 10000
}
Here is an example lambda function that receives a Kinesis event input and processes the messages:
exports.handler = async event => {
event.Records.forEach(record => {
// Kinesis data is base64 encoded so decode here
const payload = Buffer.from(record.kinesis.data, 'base64').toString('ascii');
console.log('Decoded payload:', payload);
});
};
Retry behavior of different invocation model
Invocation Model | Retry Behavior |
---|---|
Synchronous | None |
Asynchronous | Twice |
Pool Based | Retry based on data expiration |
Now you know 3 different ways to invoke Lambda functions. If you have questions or suggestions please feel free to let me know in the comments.
Top comments (0)