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 the layers folder and select the serverless.yml file. Replace the file content with the following configuration.
service: layersprovider: 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 services to reference the layer version.
todos — serverless.yml
service: todosprovider: name: aws runtime: nodejs12.xfunctions: 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: usersprovider: name: aws runtime: nodejs12.xfunctions: 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.