AWS Lambda Powertools

An open source set of utilities managed by AWS that provide out of the box functionality for tracing, logging, custom metrics, middleware, etc., for Serverless Functions. These tools help teams implement best practices around Serverless development with little overhead. You can install the tools using pip.

pip install aws-lambda-powertools

All of the following examples are available in the power-tools template project.

cdev init demo --template power-tools
cdev deploy
More Information
To learn more about the tool you can read this blog from AWS. The power tools library contains more constructs than listed here, and we are working hard on making the Cdev framework work with them.


The tracing library provides a wrapper over AWS X-Ray that allows you to quickly get started by using the @tracer annotation. To send traces to AWS X-Ray, you will need to give your function the correct permissions, which you can grant with the AWS Managed role AWSXRayDaemonWriteAccess.

Using AWS Managed Roles

You can use any AWS Managed IAM Role by wrapping it in a PermissionArn Object.

from cdev.resources.simple.iam import PermissionArn

tracer_permission = PermissionArn("arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess")
from aws_lambda_powertools import Tracer from import ServerlessFunction from src.examples.config import powertool_vars, tracer_permissions tracer = Tracer() # Sets service via env var def collect_payment(charge_id: str): print(f"Collected charge: {charge_id}") @ServerlessFunction("tracer_example", environment=powertool_vars, permissions=[tracer_permissions]) @tracer.capture_lambda_handler def handler(event, context): charge_id = event.get('charge_id') payment = collect_payment(charge_id)
cdev run function.execute power_tools.tracer_example --event-data "{\"charge_id\":\"123\"}"
cdev run function.logs power_tools.tracer_example


The logger libraries provide a standardized interface for logging information. By default, it outputs the logs as structured JSON.

from aws_lambda_powertools import Logger from import ServerlessFunction from src.examples.config import powertool_vars logger = Logger(service="payment") @ServerlessFunction("logger_example", environment=powertool_vars) @logger.inject_lambda_context def handler(event, context):"Collecting payment"){ "operation": "collect_payment", "charge_id": event['charge_id'] })

cdev run function.execute power_tools.logger_example --event-data "{\"charge_id\":\"123\"}"
cdev run function.logs power_tools.logger_example


Create custom metrics are asynchronously captured by AWS Cloudwatch.

from aws_lambda_powertools import Metrics from aws_lambda_powertools.metrics import MetricUnit from import ServerlessFunction from src.examples.config import powertool_vars metrics = Metrics(namespace="ExampleApplication", service="booking") @ServerlessFunction("metrics_example", environment=powertool_vars) @metrics.log_metrics def lambda_handler(evt, ctx): metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=123)
cdev run function.execute power_tools.metrics_example
cdev run function.logs power_tools.metrics_example
Using Multiple Libraries
You can mix and match all the available libraries, but when using multiple annotations on the same handler, you should have metrics.log_metrics as the top annotation.


The Middleware library provides the ability to execute functionality before and after your defined handler. This is a powerful way of encapsulating functionality that is shared across many handlers. For example, it can be used to validate the given data in an external database before triggering the actual functionality.

# Generated as part of Quick Start project template from aws_lambda_powertools.middleware_factory import lambda_handler_decorator from import ServerlessFunction @lambda_handler_decorator def middleware_before_after(handler, event, context): print(f"BEFORE") # logic_before_handler_execution() response = handler(event, context) # logic_after_handler_execution() print(f"AFTER") return response @ServerlessFunction("middleware_example") @middleware_before_after def lambda_handler(event, context): print('Hello from inside your Function!')
cdev run function.execute power_tools.middleware_example
cdev run function.logs power_tools.middleware_example

Data Classes

Although all AWS Serverless Functions by default should conform to the same signature , it can be helpful to have typing information about the event that is triggering the function. This information can help you to understand the structure of the data inside the function. The powertools library provides a set of classes to wrap a triggering Event to provide this additional information. A list of all the available events can be found on the official documentation pages.

from aws_lambda_powertools.utilities.data_classes import event_source, APIGatewayProxyEventV2 from import Api from import ServerlessFunction from cdev import Project as cdev_project myProject = cdev_project.instance() DemoApi = Api("demoapi") hello_route = DemoApi.route("/helloworld", "GET") @ServerlessFunction("dataclass_example", events=[hello_route.event()]) @event_source(data_class=APIGatewayProxyEventV2) def lambda_handler(event: APIGatewayProxyEventV2, context): if 'helloworld' in event.path and event.http_method == 'GET': print("Made it here!")
cdev output power_tools.api.demoapi.endpoint
curl <your_url>/helloworld
cdev run function.logs power_tools.dataclass_example
Data Classes Limitations

The implementation of Data Classes do not provide any guarantees of data validation. If an event does not conform to the expected form of a certain Data Class, it will not throw an error until a non-existent property is accessed. For example, triggering the above function directly will lead to an error.

cdev run function.execute power_tools.dataclass_example

For strong data validation, considering using the Parser library in powertools.