AWS Lambda Layers: Getting Started Guide

Many projects share common libraries around different functions. When some of the dependencies get updated, you need to be able to manage these functions independently so that other libraries not being updated are not changed. And what if someone is using the wrong version of your dependency or is using a similar library but not the one you picked?

Dependency management is important on any project, as you need to have consistent dependencies around all of your functions. Also, sometimes picking the wrong dependencies can lead to security concerns or even legal issues.

One way to protect your project from such problems is by using AWS Lambda Layers.

What are Lambda Layers?

A Lambda Layer is a ZIP archive that contains libraries. Layers are very useful if you have various Lambda functions using the same dependencies since the dependencies will be imported into the Lambda function at runtime. The main benefit of this is that you utilize your dependencies more efficiently, resulting in smaller deployment packages. And with smaller packages, you get faster deployments.

This is important for many reasons. For example, if you are running into the error “CodeStorageExceeded,” you can make your deployment packages smaller by placing all dependencies in one layer and using that layer in all of your functions. This way, you greatly reduce the size of your function packages and get around the error.

Before Lambda Layers came along, it was always a good practice to package your common libraries together and use them in Lambda. This was because the code organization was—and still is—very important when working with serverless. In this article, Yan Cui notes how important it is that your functions are simple and single purpose. And if we extract most of the dependencies from the functions, they become ever smaller and simpler.

How Lambda Layers Work

Functions can have up to five different layers, but the total size of the Lambda deployment package with all layers unzipped should not be more than 250 MB. AWS Lambda limits are thus something you need to keep in mind when combining different Lambda Layers of various sizes.

Writing & Deploying Layers in Serverless

To follow the following tutorial, you will need to have a serverless framework installed and configured. If you don’t, you can follow the instructions on how to do so here.

Let’s first create a new serverless framework project. You don’t need much for this project and can simply start by creating an empty file named “serverless.yml” in a new directory.

Here you can type something like this:

service: layer-moment

provider:
 name: aws
 runtime: nodejs8.10

layers:
 MomentLayer:
   path: nodejs
   description: "moment dependencies"

Then you can create a new directory at the same level as the serverless.yml file and name it “nodejs.” There you can now run the following command from the terminal:

$ npm install moment --save

This will create a folder node_modules inside the nodejs directory that contains another folder called moment. Inside moment we will find the files that belong to our dependency. It’s good to note that Moment.js is a time library that is very useful for JavaScript development.

nodejs
|_ node_modules
  |_ moment
serverless.yml

When you have this ready, you can then deploy your serverless project from the level of your serverless.yml file. In the terminal, go ahead and write:

$ sls deploy

After running that code, you will get back something like this:

[Service Information]
service: layer-moment
stage: dev
region: us-east-1
stack: layer-moment-dev
resources: 2
api keys:
  None
endpoints:
  None
functions:
  None
layers:
  MomentLayer: arn:aws:lambda:us-east-1:<ACCOUNT_ID>:layer:MomentLayer:1

Now your Lambda Layer is deployed in AWS. Save that layer’s ARN (Amazon Resource Name), as you will need it in the next step when using this layer.

If you go to your AWS console → AWS Lambda and then to the layer’s page, it will look something like this:

Including Lambda Layers in a Serverless Project

Now you can go to an existing function in your serverless framework project, where you want to use that deployed layer and perform the following:

functions:
 hello:
   handler: handler.hello
   events:
     - http:
         method: get
         path: hello
   environment:
     NODE_PATH: "./:/opt/node_modules"
   layers:
     - arn:aws:lambda:us-east-1:<ACCOUNT_ID>:layer:MomentLayer:1

When a Lambda Layer is unzipped in the function, the libraries will be extracted to the directory /opt. You need to now add the environmental variable of the node path, so the function can find that dependency and then the reference to the layer in your function. This is where the ARN of the Lambda Layer is used.

Your function handler can be something like this:

'use strict';
const moment = require('moment');

module.exports.hello = async (event) => {
    const dateNow = moment().format("MMM Do YY");
    
    return {
        statusCode: 200,
        body: JSON.stringify({
            message: dateNow
        }),
    };
};

You can see that there is not really any reference that you are using a layer, and you don’t need to modify your code at all.

After you deploy the project using the layer, you can check your AWS Console for your particular Lambda function. You will see something like this:

You can use any Lambda Layers you want in your project–ones you create and deploy in the same account as your project, deployed in other accounts, or even deployed by third parties. For example, Epsagon has their own layer that you can use in a similar way. And if you add in Epsagon’s one-click monitoring with the Epsagon layer, you have a very simple way to monitor your serverless applications and instrument your functions at the same time.

Important Info When Using Layers

One important thing to keep in mind is that Lambda Layers don’t help reduce cold starts. The benefit you get when using Layers is that your deployment package to Lambda is smaller. But Lambda then combines this layer with the deployed function code and deploys it in your virtual container when doing a Lambda start. So, the size of the package that will be deployed when a Lambda starts will be the size of the function plus the size of all the layers it uses.

Another important note is that nowadays it is not possible to update the version of a Lambda Layer automatically when the layer gets updated. So when a new version of a layer is updated, you need to update the version of the layer in the serverless.yml file and redeploy the function.

Also, be aware that if you’re running local testing of your functions that are using Lambda Layers with dependencies, you will need to create a workaround in your project to support this. If you don’t do this, your local tests will fail because the dependencies are not installed in the project.

Conclusion

Lambda Layers are a pretty nice way to package your dependencies. The best use cases are when you have a lot of common dependencies that you share between your functions and want to have control over version updates and management. They are also great when you are using layers created and managed by third parties.

By using Layers, you can avoid the issue of every function in your application using a different version or dependency or even a similar library. This way, you will achieve an application that is simpler and easier to manage.

However, make sure not to abuse Lambda Layers. You can only have five layers per function, and your function has a limited deployment package size. If some layers are very big, resulting in a Lambda deployment package that exceeds 250 MB unzipped, the deployment can result in errors.

Interested to learn more? Sign up to our weekly live demo!