Utilizing Lambda Layers for Code Reuse and External Library Integration
What Are Lambda Layers?
Lambda Layers are essentially ZIP archives containing libraries, custom runtime environments, or other dependencies. You can include these layers in your Lambda function’s execution environment without having to bundle them directly with your function's deployment package. This means you can use libraries or custom runtimes across multiple Lambda functions without needing to include them in each function’s codebase.
How They Work
When you create a Lambda function, you specify which layers to include in its execution environment. During execution, AWS Lambda configures the function's environment to include the content of the specified layers. This content is available to your function's code just as if it were included in the deployment package directly.
Use Cases
- Sharing code: Commonly used code can be placed in a layer and shared among multiple functions.
- Custom runtimes: You can use layers to deploy functions in languages that AWS Lambda does not natively support by including the necessary runtime in a layer.
- Configuration files: Layers can be used to store configuration files that multiple functions need to access.
AWS Lambda Development with Custom Layers
Forge streamlines the process of creating and sharing custom layers across AWS Lambda functions, significantly simplifying code reuse and management. This section walks you through creating a custom layer using Forge, integrating it into your development workflow, and utilizing it within a Lambda function.
Creating a Custom Layer
To begin, execute the following command to create a custom layer named my_custom_layer
:
This command sets up a specific directory structure for your layer within your project, organizing the code efficiently:
Forge not only initializes the necessary structure but also populates my_custom_layer.py with a starter function. This function acts as a blueprint for your shared code:
def hello_from_layer():
return "Hello from my_custom_layer layer!"
Additionally, Forge sets the new custom layer in the Layers class.
from aws_cdk import aws_lambda as _lambda
from lambda_forge.path import Path
class Layers:
def __init__(self, scope) -> None:
self.my_custom_layer = _lambda.LayerVersion(
scope,
id='MyCustomLayer',
code=_lambda.Code.from_asset(Path.layer('layers/my_custom_layer')),
compatible_runtimes=[_lambda.Runtime.PYTHON_3_9],
description='',
)
Traditionally, working with Lambda layers introduces complexity during development. Since Lambda layers are deployed as zip files and run within the Lambda execution environment, developers usually face challenges in utilizing these layers locally. This often leads to a disconnect between development and production environments, complicating the development process.
When you create a custom layer using Forge, the new layer is automatically integrated into your local virtual environment, similar to installing an external library from pip. However, to ensure that these changes are fully recognized, you may need to reload your IDE or reselect your virtual environment.
Note
In case you need to reinstall the custom layers into your virtual environment, use the command:Creating a Lambda Function Utilizing the Custom Layer
Create a new Lambda function that leverages your custom layer by running:
This command simply creates a public function named custom
inside the functions
directory.
Now, implement the function to utilize the custom layer:
import json
from dataclasses import dataclass
import my_custom_layer
@dataclass
class Input:
pass
@dataclass
class Output:
message: str
def lambda_handler(event, context):
message = my_custom_layer.hello_from_layer()
return {"statusCode": 200, "body": json.dumps({"message": message})}
Finally, configure the function to make use of the my_custom_layer
layer:
from infra.services import Services
class CustomConfig:
def __init__(self, services: Services) -> None:
function = services.aws_lambda.create_function(
name="Custom",
path="./functions/custom",
description="A function to make use of the custom layer",
layers=[services.layers.my_custom_layer],
)
services.api_gateway.create_endpoint("GET", "/custom", function, public=True)
Once you've committed and pushed your code to GitHub and the pipeline has successfully executed, making a GET request to the generated URL should return the following response:
The URL for this tutorial is:
AWS Lambda Development with External Libraries
In software development, using external libraries is a common practice to extend functionality and streamline the development process. When working with AWS Lambda, incorporating these external libraries requires integrating them as layers into our Lambda functions.
To illustrate this scenario, we will develop a new lambda function aimed to parsing the data retrieved from the external API https://randomuser.me/api/, a public service for generating random fake user data. Since the requests
library is not inherently included in Python, it will be necessary to integrate it as a layer in our lambda function.
To create an external layer, run the following command in your terminal:
Incorporating Requests from Public Layers
To create a new layer for the requests library, simply run:
Lambda Forge will automatically create and deploy this layer to AWS, additionally it updates the Layer
class to utilize your newly created layer.
Creating a Lambda Function Utilizing the Requests Library
To create a Lambda function that leverages the Requests library, execute the following command:
forge function external --method "GET" --description "A function that uses an external library" --public
This command creates a new function named external
inside the functions directory.
Now, implement the function to utilize the custom layer:
import json
from dataclasses import dataclass
import requests
@dataclass
class Input:
pass
@dataclass
class Name:
title: str
first: str
last: str
@dataclass
class Output:
name: Name
gender: str
email: str
def lambda_handler(event, context):
result = requests.get("https://randomuser.me/api").json()["results"][0]
data = {
"name": result["name"],
"gender": result["gender"],
"email": result["email"],
}
return {"statusCode": 200, "body": json.dumps({"data": data})}
Additionally, update the unit tests to expect the correct output message:
import json
from .main import lambda_handler
def test_lambda_handler():
response = lambda_handler(None, None)
body = json.loads(response["body"])
assert ["name", "gender", "email"] == list(body.keys())
Finally, configure the function to make use of the requests layer:
from infra.services import Services
class ExternalConfig:
def __init__(self, services: Services) -> None:
function = services.aws_lambda.create_function(
name="External",
path="./functions/external",
description="A function that uses an external library",
layers=[services.layers.requests_layer],
)
services.api_gateway.create_endpoint("GET", "/external", function, public=True)
Once you've committed and pushed your code to GitHub and the pipeline has successfully executed, making a GET request to the generated URL should return the following response:
For this tutorial, the generated URL is: