Sharing Code among Lambdas using Lambda Layers

What?

Lambda layers allow us to share code among lambda functions. We just have to upload the layer once and reference it in any lambda function.

The code in a layer could be anything. It could be dependencies, configurations, helper functions i.e. Logging, Recording metrics, etc…

We can link up-to five lambda layers per function where one of that can optionally be a custom runtime e.g. PHP, rust, etc.. However adding your custom runtime is not the most frequent use-case for lambda layers but sharing code across your serverless microservices.

Why?

Lambda layers were announced at the reInvent of 2018. The main purpose of a lambda layer is to avoid duplicate codes across many lambdas thereby promote separation of concerns design principle.

Before lambda layers, developers used to either duplicate common code in every lambda function or create local npm packages and refer them in lambdas. Now with lambda layers, you can securely share code among your lambda functions in the same AWS account, cross-accounts or in public.

How?

You can use the AWS console directly to deploy lambda layers. However, it is not recommended for production applications. Most people use either Serverless Framework or AWS SAM CLI (Serverless Application Model) to deploy and manage lambda layers.

Here is an example using the Serverless Framework.

Step 01 — Install serverless framework

Open a terminal or a command prompt and create a new folder called “backend”.

mkdir backend

Open the folder in VS Code.

Let’s install the serverless framework globally using npm. Lambda layer support is added to newer versions of the serverless framework.

npm install -g serverless

Step 02 — Create serverless services

Now let’s create three serverless services i.e. layers, todos, and users. Inside the backend folder run following commands in serverless to create above nodejs services.

Layer service

serverless create --template aws-nodejs --path layers

Todo service

serverless create --template aws-nodejs --path todos

User service

serverless create --template aws-nodejs --path users

Step 03 — Creating a lambda layer

Open layers folder and select the serverless.yml file. Replace the file content with the following configuration.

service: layers
provider:
name: aws
runtime: nodejs12.x
layers:
logging:
path: logging

In the above configuration, we reference logging layer with the path logging. Let’s now add a folder called logging in the layers folder.

mkdir logging

Since we are using nodejs runtime, we have to create a certain folder structure in the logging folder, so that other lambda functions can access the logging layer code.

NodeJS path — nodejs/node_modules/<module_name>/<files>

So, I’ve created the above folders as shown in the picture below.

index.js

Below is the content inside index.js of the logging module. For testing purposes, let’s return a simple text.

module.exports.log = () => {
return 'Logging from layer';
};

Step 04 — Deploying the lambda layer

Now that we have created the sample logging layer, let’s go ahead and deploy it into AWS.

Make sure that you have correctly configured the access keys and secret access keys with the serverless framework. If you haven’t done so, use the below command.

serverless config credentials --provider aws --key <access_key> 
--secret <secret_key>

Deploying the layer

Run the following command inside the layers folder where the serverless.yml file resides.

serverless deploy --stage dev

The above command will deploy the layer into the given stage (dev) in AWS.

Output

Copy the arn of the lambda layer version. We will add this arn to todos and users microservices so that they can reference the lambda layer.

Step 05 — Using the layer in other lambdas

Let’s use the layer we have created in step 04 in todos and users service. We need to edit the serverless.yml file in both the services to reference the layer version.

todos — serverless.yml

service: todos
provider:
name: aws
runtime: nodejs12.x
functions:
todos:
handler: handler.todos
layers:
- arn:aws:lambda:us-east-1:885121665536:layer:logging:9
events:
- http:
path: todos
method: get

users — servereless.yml

service: users
provider:
name: aws
runtime: nodejs12.x
functions:
users:
handler: handler.users
layers:
- arn:aws:lambda:us-east-1:885121665536:layer:logging:9
events:
- http:
path: todos
method: get

Usage in the handler function

We have configured the servereless.yml configuration files of the two services above so that our lambdas have access to the logging layer.

How can we reference the log() function in a lambda handler function?

todos/handler.js

'use strict';
const logging = require('logging');
module.exports.todos = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
message: logging.log()
}, null, 2)
}};

It’s as simple as referencing a usual npm dependency using the require keyword.

Now we can invoke log() function in the logging module.

Note — Deploy both todos and users services using ‘serverelss deploy’ and then you can see the logging messages by accessing API gateway endpoints. The endpoints can be found in the output log of serverless deploy command.

Concerns

Here are some concerns about lambda layers worth noting.

  • A lambda function can reference only up to 5 layers
  • If you have multiple lambda layers, the order is important as the lambda layers depend upon each other. (This is useful when adding a custom runtime layer)
  • Layers are immutable and can be versioned to manage updates
  • You can share layers securely (Using IAM) within your AWS account, cross-accounts and even in public

Limits

A lambda layer is just a blob of data in a zip file. The uncompressed size of a lambda layer must be less than 250MB. This is a limit set by AWS.

Please follow and like us: