Chaining Lambda Functions using the Serverless Framework — Part 2

Noah Ispas
4 min readFeb 11, 2019

In my first article about chaining Lambda Functions, I showed how you can invoke a Lambda from another Lambda Function by directly invoking it. This time we will decouple it a little bit by using a Message Queue(the Message Queue Service of AWS is called SNS, short for Simple Notification Service) to realize the invocation.

TL;DR

Here you can find a GitHub repository if you want a quick start

Prerequisites

At least for the prerequisites you should check my previous article

Create Lambda Function

Now we are good to go, so lets create a new project using the Serverless Framework

Bootstrap Project

First create a project

serverless create --template aws-nodejs --path lambda-chaining-2

Move to the generated project and a dependency to the aws-sdk module

npm install --save aws-sdk

Prepare Environment

The Serverless Framework allows to set AWS IAM access rights, which we are going to need in order to grant rights for sending messages through a Message Queue. Paste the following in your serverless.yml

service: lambda-chaining-2
provider:
name: aws
runtime: nodejs6.10
iamRoleStatements:
- Effect: "Allow"
Resource: "*"
Action:
- "sns:*"

Define Lambda Functions

Finally we can define two Lambda Functions, therefore we create the following functions in the handler.js

'use strict'
const aws = require('aws-sdk')
module.exports.hello = (event, context, callback) => {
let sns = new aws.SNS()
let opts = {
Message: 'payload from invoking lambda',
TopicArn: process.env.mySnsTopicArn,
};
sns.publish(opts, (err, data) => {
if (err) {
console.log('error while sending message over sns: ' + err)
callback(err, null)
} else {
const response = {
statusCode: 200,
body: 'message sent'
}
callback(null, response)
}
})
}
module.exports.ciao = (event, context, callback) => {
let message = event.Records[0].Sns.Message
console.log("received msg: " + message)
const response = {
statusCode: 200,
body: 'ciao world'
}
callback(null, response)
}

In order to send a message through the SNS, we have to define a topic on which we want to send the message. We will specify the topic by using an environment variable, which I will explain in the following sections

Define Custom Parameter

The next step is to create some custom parameters for referencing the topic we mentioned in the section before. Therefore we add the following to the root level of our serverless.yml

custom:
mySnsTopic: "chain"
mySnsTopicArn: "arn:aws:sns:#{AWS::Region}:#{AWS::AccountId}:${self:custom.mySnsTopic}"

You may wonder why we need 2 variables instead of just one. The answer is simple. It is because for a Lambda Function to listen on a certain topic, it just needs to know the name of the topic, in this case ‘chain’. But the Lambda Function that wants to sent something to a topic, needs to know the whole ARN of the topic.

Note: In order for this to work you need to have the serverless-pseudo-parameters plugin added to your project

Define handler

In the last step we connect our functions to the respective Lambda Function handlers in the serverless.yml

functions:
hello:
handler: handler.hello
environment:
mySnsTopicArn: ${self:custom.mySnsTopicArn}
ciao:
handler: handler.ciao
events:
- sns: ${self:custom.mySnsTopic}

Note that the environment variable which gets injected to the hello Lambda Function refers to the created topic ARN variable that we created in the custom section, while the ciao Lambda only refers to the topic name variable.

Deploy Lambda Functions

At this point we could deploy our Lambda Functions

serverless deploy -v

You should see verbose output and if everything went fine you can see your Lambda Functions in the respective AWS console view. Just be sure to select the right region.

Invoke Lambda Function

Now you can invoke our first Lambda Function which should call the second one in a decoupled fashion over SNS. This time it will just return something like: 200, ‘message sent’

serverless invoke -f hello -l

But when you have a look at the logs of the ciao Lambda Function, you will see that it was invoked and logged something on the console. You can simply see that by using the following command

serverless logs -f ciao

Conclusion

Im comparison to chaining Lambda Functions by invoking one another directly through their ARN, now we have an event based way of chaining them which also results in better decoupling of Lambda Functions. You don’t need to know the ARN of Lambda Functions anymore, you just need to know about SNS topics. Also with this method we can invoke more than just one Lambda Function by sending a message to a SNS topic.

Another interesting aspect is (a)synchronicity, or blocking source code. If you invoke a Lambda Function (by direct invocation) and need the result from it, it could happen that the code of the invoking Lambda Function blocks until the invoked Lambda returns. By decoupling the Lambda Functions and work in a more event based fashion, you can prevent blocking.

Well that’s it, have fun playing around with chaining your Lambda Functions through SNS.

Cheers

Noah

Links

--

--

Noah Ispas

Inspire and helping people to do what they love and do best. Connecting the dots and creating harmonious environments.