Lambda Calling Lambda

There are many ways for a Lambda function to invoke another Lambda function. The first is to use the AWS SDK directly.

JavaScript

Here’s an example using the JavaScript SDK:

var aws = require('aws-sdk');
var lambda = new aws.Lambda({
  region: 'us-west-2'
});
lambda.invoke({
  FunctionName: 'my-function',
  Payload: JSON.stringify(event, null, 2)
}, function(error, data) {
  if (error) {
    context.done('error', error);
  }
  if (data.Payload){
   context.succeed(data.Payload)
  }
});

See Lambda.invoke’s documentation here.

Python

The same can be done using Boto 3:

from boto3 import client as boto3_client
import json
lambda_client = boto3_client('lambda')
def lambda_handler(event, context):
    invoke_response = lambda_client.invoke(FunctionName = "my-function",
                                           InvocationType = 'Event',
                                           Payload = json.dumps({"message":"hi"}))
    print(invoke_response)

That’s async invocation. For sync, do this:

from boto3 import client as boto3_client
import json
lambda_client = boto3_client('lambda')
def lambda_handler(event, context):
    invoke_response = lambda_client.invoke(FunctionName = "my-function",
                                           InvocationType = 'RequestResponse',
                                           Payload = json.dumps({"message":"hi"}))
    print(invoke_response['Payload'].read().decode())

Java

AWSLambdaAsync awsLambdaAsync = AWSLambdaAsyncClientBuilder
    .standard().withRegion("us-east-1").build();

InvokeRequest invokeRequest = new InvokeRequest();
invokeRequest.withFunctionName("my-function").withPayload(payload);

InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest);

Here’s a detailed blog post from AWS for the same — Invoking AWS Lambda Functions from Java.

API

You can also send a signed HTTP POST request to the function’s invocation endpoint directly:

POST /2015-03-31/functions/FunctionName/invocations?Qualifier=Qualifier HTTP/1.1
X-Amz-Invocation-Type: InvocationType
X-Amz-Log-Type: LogType
X-Amz-Client-Context: ClientContext

Payload

If you invoke a function synchronously, remember that the caller is waiting (& blocked) for the callee’s response. During this time, you’re paying for both Lambdas, even though only one of them is doing anything productive!

To invoke a function asynchronously, set InvocationType to Event. But remember that if you invoke a function asynchronously and it returns an error, Lambda executes the function up to two more times.

For asynchronous invocation, Lambda adds events to a queue before sending them to your function. If your function does not have enough capacity to keep up with the queue, events may be lost. Occasionally, your function may receive the same event multiple times, even if no error occurs. To retain events that were not processed, configure your function with a dead-letter queue.

For functions with a long timeout, your client might be disconnected during synchronous invocation while it waits for a response. Configure your HTTP client, SDK, firewall, proxy, or operating system to allow for long connections with timeout or keep-alive settings.

Ensure that the caller Lambda function has permissions to perform the lambda:InvokeFunction action. See Lambda documentation for Invoke.

If the caller Lambda is inside a VPC & the called Lambda is not, you must configure the subnet containing the caller Lambda to have outbound internet access. Otherwise, the Lambda invocation call fails without any error!

Lambda > SNS > Lambda

In many cases, it’s actually better to publish a message to an SNS topic from a Lambda function & have other functions subscribe to the topic. This decouples the system & makes it much more scalable & resilient. Here’s a great blog post from AWS about it — Invoking AWS Lambda functions via Amazon SNS. BTW, SNS doesn’t charge for delivering messages to Lambda.

SNS is also great for cross-account Lambda invocations. See Using Amazon SNS for system-to-system messaging with an AWS Lambda function as a subscriber & Tutorial: Using AWS Lambda with Amazon Simple Notification Service.

But if you need to invoke functions synchronously & maybe act on their response, direct function-to-function call is the way to go. SNS isn’t suitable there.

Step Functions for Orchestration

If you’re building a workflow of inter-dependent tasks using Lambda functions, step functions are a much better solution that calling functions from other functions directly. Step functions can handle the passing of one function’s output to another function as input for you. You can also build conditional logic based on the success/failure or response value of a function.

Here’s a simple step functions spec that invokes 2 functions:

{
  Comment: "Quote and Order",
  StartAt: "ProduceQuote",
  States: {
    ProduceQuote: {
      "Type": Task,
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      "next": TurnToOrder
    }
    TurnToOrder: {
      Type: Task,
      Resource: "arn:aws:lambda:us-east-1:123456789012:function:TurnToOrder",
      end: true
    }
  }
}

Kinesis

In extremely high-volume cases, where some Lambda functions generate a large number of messages intended for consumption by other Lambda functions, Kinesis might be a better fit. Unlike SNS, Kinesis will save your messages for some time. Using Kinesis or SNS will also help avoid hitting your Lambda’s concurrent execution threshold.