474

I have 2 Lambda functions - one that produces a quote and one that turns a quote into an order. I'd like the Order lambda function to call the Quote function to regenerate the quote, rather than just receive it from an untrusted client.

I've looked everywhere I can think of - but can't see how I'd go about chaining or calling the functions...surely this exists!

9
  • 2
    I'm reaching here, but why couldn't you depend on the AWS JavaScript SDK in the first Lambda function, create an AWS.Lambda client and invoke the second function? Commented Jul 30, 2015 at 3:52
  • 1
    apparently you can also invoke a Lambda function through HTTP. Commented Jul 30, 2015 at 3:59
  • 4
    and one more idea, you could chain them through SNS, which is probably the way I'd go as a more scalable strategy Commented Jul 30, 2015 at 4:01
  • 9
    Another common alternatives not being mentioned here are Step Functions or SWF. Commented Nov 3, 2017 at 19:46
  • 1
    Can I call the other Lambda if it resides inside a VPC and the caller lambda is outside that VPC? Commented Jun 2, 2020 at 19:36

24 Answers 24

502

I found a way using the aws-sdk.

var aws = require('aws-sdk');
var lambda = new aws.Lambda({
  region: 'us-west-2' //change to your region
});

lambda.invoke({
  FunctionName: 'name_of_your_lambda_function',
  Payload: JSON.stringify(event, null, 2) // pass params
}, function(error, data) {
  if (error) {
    context.done('error', error);
  }
  if (data.Payload) {
    context.succeed(data.Payload);
  }
});

You can find the doc here: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html

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

9 Comments

Using SNS is probably the better approach, but this is the correct answer.
i could be wrong, but I think because the invocation is synchronous that the first lambda waits for the second lambda to terminate, thus you will be accruing charges while both lambdas are running. using SNS, the first lambda should terminate and allow the second lambda to execute independently.
I was able to get this to work thanks to the InvocationType: 'Event' parameter (add it after FunctionName and Payload). From the docs: "You can optionally request asynchronous execution by specifying Event as the InvocationType." With async execution, the callback function will be reliably called, but without having to wait for the invoked lambda to finish executing.
Note that the calling lambda function's role needs to include IAM policy AWSLambdaRole. Or, you can add the following statement object to your role's existing policy: '{ "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": ["*"] }`
Also, be cautious when using this approach for calling the function itself. You might end up in an infinite invocation loop and the only way to stop the invocations, in that case, is be uploading a new version of the code.
|
166

You should chain your Lambda functions via SNS. This approach provides good performance, latency and scalability for minimal effort.

Your first Lambda publishes messages to your SNS topic and the second Lambda is subscribed to this topic. As soon as messages arrive in the topic, the second Lambda is executed with the message as its input parameter.

See Invoking Lambda functions using Amazon SNS notifications.

You can also use this approach to Invoke cross-account Lambda functions via SNS.

14 Comments

"You should chain your Lambda functions via SNS" -- can you support this with evidence/links to docs? I see how both methods would work, I would be interested in seeing some opinions / definite statements on which one is the preferred one
This is a good idea if you need it to be asynchronous. But if your first lambda function needs the returned value from the second lambda, you have to chain the lambdas and have the first lambda function invoke the second lambda function directly.
I wouldn't recommend using SNS. You can just utilize the asynchronous invocation API for the lambda function-no reason to use SNS unless you want to notify multiple subscribers and not just trigger another lambda function.
Keep in mind that SNS does not have delivery guarantee so you'd might fire the message but it might not arrive.
In order to solve the problem of delivery guarantee you can notify to an SQS queue and use retry patters to ensure the successfully processing the data. aws.amazon.com/sqs/faqs
|
111

Here's a sample code for python,

from boto3 import client as boto3_client
from datetime import datetime
import json

lambda_client = boto3_client('lambda')

def lambda_handler(event, context):
    msg = {"key": "new_invocation", "at": datetime.now().isoformat()}
    invoke_response = lambda_client.invoke(FunctionName="another_lambda_",
                                           InvocationType='Event',
                                           Payload=json.dumps(msg))
    print(invoke_response)

Btw, you would need to add a policy like this to your lambda role as well

   {
        "Sid": "Stmt1234567890",
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": "*"
    }

8 Comments

The documentation seems to suggest the payload must be JSON. Is it possible to send binary data?
I prefer this method also, but it's got one glitch. You'll need to convert the datetime.now() to a string (or handle it somehow). Otherwise, you get the error datetime.datetime(2017, 9, 11, 14, 40, 53, 23834) is not JSON serializable
Is it possible to be more restrictive in the first lambda's role? Ie, to tie it down to invoking specific functions, rather than any and all?
The InvocationType should be: RequestResponse. To get the response from the lambda that you are trying to invoke.
And then if you have InvocationType to RequestResponse you should print print(invoke_response['Payload'].read().decode()) to properly print the response message
|
56

Since this question was asked, Amazon has released Step Functions (https://aws.amazon.com/step-functions/).

One of the core principles behind AWS Lambda is that you can focus more on business logic and less on the application logic that ties it all together. Step functions allows you to orchestrate complex interactions between functions without having to write the code to do it.

Comments

19

This solution is done using boto3 and Python:

import boto3
import json

lambda_client = boto3.client('lambda', region_name='eu-west-1')

def lambda_handler(event, context):
    lambda_client.invoke(FunctionName = 'function_name', InvocationType = 'RequestResponse', Payload = json.dumps(event))
    
    return True

1 Comment

InvocationType Choose from the following options. RequestResponse (default) - Invoke the function synchronously. Keep the connection open until the function returns a response or times out. Event - Invoke the function asynchronously. Send events that fail multiple times to the function's dead-letter queue (if configured). DryRun - Validate parameter values and verify that the user or role has permission to invoke the function.
13

I was looking at cutting out SNS until I saw this in the Lambda client docs (Java version):

Client for accessing AWS Lambda. All service calls made using this client are blocking, and will not return until the service call completes.

So SNS has an obvious advantage: it's asynchronous. Your lambda won't wait for the subsequent lambda to complete.

5 Comments

InvocationType='Event' makes it async. docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/…
@Ankit that should be the selected answer, I was misled to believe using SNS was the only way to do an asynchronous invocation because nobody answered with this information.
@Ankit do you know of an example using InvocationType='Event' but from Java instead of JavaScript? There is a ton of Java documentation, but not nearly as many examples as JavaScript
SNS still adds costs for it's usage
@SebastienH. There is no cost for SNS invoking Lambda. aws.amazon.com/sns/pricing
12

Amazon has introduced steps functions in AWS lambda in 2016. I think, now it's more convenient to use steps function as it's really easy to use them. You can build a state machine with two lambda functions as:

  • to produces a quote
  • turns a quote into an order

You can easily do that as below:

Here you can have first state for produces a quote and another to turns into order

{
  Comment: "Produce a quote and turns into an order",
  StartAt: "ProduceQuote",
  States: {
    ProduceQuote: {
      "Type": Task,
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      "next": TurnsToOrder
    }
    TurnsToOrder: {
      Type: Task,
      Resource: "arn:aws:lambda:us-east-1:123456789012:function:ProduceQuote",
      end: true
    }
  }
}

Steps functions makes it really easy to write multiple lambda functions and run in sequence or in parallel. You can get more information about lambda steps functions here: Steps Functions

Comments

10

There are a lot of answers, but none is stressing that calling another lambda function is not recommended solution for synchronous calls and the one that you should be using is really Step Functions

Reasons why it is not recommended solution:

  • you are paying for both functions when they are waiting for each other
  • your code is responsible for retrials

You can also use it for quite complex logic, such as parallel steps and catch failures. Every execution is also being logged out which makes debugging much simpler.

Comments

6

In java, we can do as follows :

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

InvokeRequest invokeRequest = new InvokeRequest();
invokeRequest.withFunctionName("youLambdaFunctionNameToCall").withPayload(payload);

InvokeResult invokeResult = awsLambdaAsync.invoke(invokeRequest); 

Here, payload is your stringified java object which needs to be passed as Json object to another lambda in case you need to pass some information from calling lambda to called lambda.

1 Comment

how can i pass path parameters that is required by the target lambda?
5

I was working with the answer provided by blueskin but I could not read the Payload response because the InvocationType='Event' is async, so I changed as InvocationType='RequestResponse' and now all works good.

Comments

3

You might be able to make use of the Async.js Waterfall feature - see the bottom part of the big code chunk in Step 3 of this document for an example:

https://aws.amazon.com/blogs/compute/better-together-amazon-ecs-and-aws-lambda/

Comments

3

Others pointed out to use SQS and Step Functions. But both these solutions add additional cost. Step Function state transitions are supposedly very expensive.

AWS lambda offers some retry logic. Where it tries something for 3 times. I am not sure if that is still valid when you trigger it use the API.

Comments

3

Here is the python example of calling another lambda function and gets its response. There is two invocation type 'RequestResponse' and 'Event'. Use 'RequestResponse' if you want to get the response of lambda function and use 'Event' to invoke lambda function asynchronously. So both ways asynchronous and synchronous are available.

    lambda_response = lambda_client.invoke(
                FunctionName = lambda_name,
                InvocationType = 'RequestResponse',
                Payload = json.dumps(input)
                )
    resp_str = lambda_response['Payload'].read()
    response = json.loads(resp_str)

Comments

2

You can invoke lambda function directly (at least via Java) by using AWSLambdaClient as described in the AWS' blog post.

Comments

2

I'm having the same problem but the Lambda function that I implement will insert an entry in DynamoDB, so my solution uses DynamoDB Triggers.

I make the DB invoke a Lambda function for every insert/update in the table, so this separates the implementation of two Lambda functions.

Documentation is here: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html

Here is a guided walkthrough: https://aws.amazon.com/blogs/aws/dynamodb-update-triggers-streams-lambda-cross-region-replication-app/

Comments

1

Kind of a roundabout solution but I just call the API endpoint for my lambda functions when I need to chain them. This allows you to decide while coding if you want them to be asynchronous or not.

In case you don't want to setup a POST request you can just setup a simple GET request with a couple, or none at all, query string parameters for easy event passing.

-- Edit --

See: https://docs.aws.amazon.com/apigateway/api-reference/making-http-requests/

and: http://docs.aws.amazon.com/lambda/latest/dg/with-on-demand-https-example.html

4 Comments

this seems a lot less roundabout than SNS, but then i don't have much experience using SNS
Can you share the code needed to call an API endpoint from within a lambda?
@Glenn it's just an ajax request. Tag on your parameters that you need to as query parameters. See: docs.aws.amazon.com/apigateway/api-reference/… and docs.aws.amazon.com/lambda/latest/dg/…
Another problem is that going through API Gateway is relatively expensive compared to calling another Lambda function. A 128MB function running for 100ms (the minimum) costs $0.21 per 1 million calls, whereas API Gateway costs $3.50 per 1 million. Obviously, if you're running for more time or you use more ram, you'd have to multiply the 21 cents, but still, $3.50 per million is really expensive. (These prices were effective as of August 2017)
1

Here is how you can do it in javascript/typescript without having to install complete aws-sdk package.

import { InvokeCommand, LambdaClient, LogType } from "@aws-sdk/client-lambda";

const client = new LambdaClient({
    region: "US-EAST-1"
});

const payload = JSON.stringify({
  data: "your input"
})

const command = new InvokeCommand({
  FunctionName: "your function name",
  Payload: payload,
  LogType: LogType.Tail,
});

const { Payload } = await client.send(command);
const response: any = Payload;
const result = Buffer.from(response).toString();

return result;

Comments

1

You might consider use the Service AWS Step Function, this allow to you orchestrate many lambdas sharing a common space of variables and data.

https://aws.amazon.com/pt/step-functions/

here there an example of a state machine:

enter image description here

Comments

0

You can trigger Lambda functions directly from other Lambda functions directly in an asynchronous manner.

https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-async-destinations

Comments

0

Calling another function from one function is considered as antipattern in server less. Its well explained here.

Better implementaion is either use queue to publish the message and consume in another lambda or use step function as described by Black

Comments

0

if you want to use a lambda function dependent on another lambda function. you can use the [State Machine] https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-state-machine-structure.html this will help you run the lambda function in sequence or based on the result of another lambda function. It also allows you to integrate other AWS Services also

Comments

0

I just noticed this older than I thought. You could have the lambdas have certain roles. So the order Lambda would need to have the regenerate-quote role. You could separate out the quote lambda to generate the original quote and then regenerate it. I think there would be some difference It doesn't sound like you need the regenerateQuote function to return back to the order lambda. You could use EventBridge to call the regenerate-quote lambda from the order lambda.

Comments

0

for calling another lambda function you can use lambda destinations feature. enter image description here

from aws documentation

AWS Lambda Destinations gives you more visibility and control of function execution results. This helps you build better event-driven applications, reducing code, and using Lambda’s native failure handling controls.

There are no additional costs for enabling Lambda Destinations. However, calls made to destination target services may be charged.

ref: https://aws.amazon.com/blogs/compute/introducing-aws-lambda-destinations/

you can even put this in to sam yaml file to aws cloudformation template.

Comments

0

2024 answer using aws sdk for javascript v3

AWS announced end of support for aws sdk v3 effective September 8 2025 - reference here.

You can invoke a 2nd lambda function from your lambda using the following:

const { InvokeCommand, LambdaClient, LogType } = require("@aws-sdk/client-lambda");
// import {InvokeCommand, LambdaClient, LogType} from "@aws-sdk/client-lambda";

const client = new LambdaClient({ region: "eu-west-2" });  // replace with your region
const command = new InvokeCommand({
  FunctionName: "my-second-lambda",   // replace with your function name
  Payload: JSON.stringify(payload),   // replace with your stringified payload
  LogType: LogType.Tail,
});

const { Payload, LogResult } = await client.send(command);
const result = Buffer.from(Payload).toString();
const logs = Buffer.from(LogResult, "base64").toString();

Note that this is a synchronous call where the first lambda will wait for the 2nd lambda's response before exiting. For asynchronous calls, where the first lambda fires and forgets add InvocationType: 'Event' to the command.

const command = new InvokeCommand({
  FunctionName: "my-second-lambda",
  Payload: JSON.stringify(payload),
  LogType: LogType.Tail,
  InvocationType: 'Event'    // for calling the 2nd lambda asynchronously
});

Reference here - https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_lambda_code_examples.html

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.