AWS Lambda Powertools is a suite of utilities for Lambda functions, available in Python, Java, .NET, and Typescript. It’s designed to simplify development in serverless applications by offering utilities for:

  • Tracing: Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions
  • Logger: Structured logging made easier, and decorator to enrich structured logging with key Lambda context details
  • Metrics: Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF)
  • Event handler AppSync: AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function
  • Event handler: API Gateway, ALB and Lambda Function URL: Amazon API Gateway REST/HTTP API and ALB event handler for Lambda functions invoked using Proxy integration, and Lambda Function URL
  • Middleware factory: Decorator factory to create your own middleware to run logic before, and after each Lambda invocation
  • Parameters: Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time
  • Batch processing: Handle partial failures for AWS SQS batch processing
  • Typing: Static typing classes to speedup development in your IDE
  • Validation: JSON Schema validator for inbound events and responses
  • Event source data classes: Data classes describing the schema of common Lambda event triggers
  • Parser: Data parsing and deep validation using Pydantic
  • Idempotency: Idempotent Lambda handler
  • Data Masking: Protect confidential data with easy removal or encryption
  • Feature Flags: A simple rule engine to evaluate when one or multiple features should be enabled depending on the input
  • Streaming: Streams datasets larger than the available memory as streaming data.

1. Tracing with AWS X-Ray

The tracing utility allows you to automatically instrument your Lambda function with AWS X-Ray. You can trace specific functions or entire Lambda invocations to identify bottlenecks and performance issues.

from aws_lambda_powertools import Tracer
 
tracer = Tracer()
 
@tracer.capture_lambda_handler
def lambda_handler(event, context):
    # Any logic here will be traced
    response = {"statusCode": 200, "body": "Hello, Lambda Powertools with X-Ray"}
    return response

Using @tracer.capture_lambda_handler on the handler function captures the entire invocation trace. For finer-grained tracing, you can use @tracer.capture_method on individual methods within the Lambda.


2. Logging

The logging utility provides structured JSON logging, making logs more readable in CloudWatch and improving traceability across services.

from aws_lambda_powertools import Logger
 
logger = Logger(service="my_service")
 
@logger.inject_lambda_context
def lambda_handler(event, context):
    logger.info("Processing Lambda request", extra={"requestId": context.aws_request_id})
    return {"statusCode": 200, "body": "Logging example"}

The @logger.inject_lambda_context decorator automatically logs context information, such as request IDs, making it easier to correlate logs for a specific invocation. You can add custom structured log fields with extra parameter.


3. Metrics with CloudWatch

The metrics utility lets you publish custom metrics to CloudWatch. This is helpful for tracking business metrics or monitoring performance.

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
 
metrics = Metrics(namespace="MyApplication")
 
@metrics.log_metrics
def lambda_handler(event, context):
    metrics.add_metric(name="SuccessfulInvocation", unit=MetricUnit.Count, value=1)
    metrics.add_metric(name="ProcessingTime", unit=MetricUnit.Milliseconds, value=150)
    return {"statusCode": 200, "body": "Metrics example"}

Using @metrics.log_metrics logs all metrics at the end of the function automatically. add_metric allows you to add multiple metrics, specifying both name and unit.


4. Idempotency

Idempotency ensures that repeated Lambda executions for the same event don’t trigger duplicate processing. This is useful in event-driven architectures where retries are common.

DynamoDB Setup: You’ll need a DynamoDB table to store the idempotency keys.

from aws_lambda_powertools.utilities.idempotency import DynamoDBPersistenceLayer, idempotent
 
persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
 
@idempotent(persistence_store=persistence_layer, data_keyword_argument="order_id")
def process_order(event):
    # This function will only run once per unique order_id
    return {"statusCode": 200, "body": "Order processed"}
 
def lambda_handler(event, context):
    order_id = event.get("order_id")
    return process_order(event={"order_id": order_id})

In this example, the @idempotent decorator ensures that process_order only processes a unique order_id once. You can set data_keyword_argument to specify the field in the event used as the idempotency key.


5. Parameters Utility

The parameters utility simplifies retrieving parameters from AWS Systems Manager Parameter Store, Secrets Manager, or DynamoDB with built-in caching.

from aws_lambda_powertools.utilities.parameters import get_parameter
 
def lambda_handler(event, context):
    # Fetch and cache parameter from SSM Parameter Store
    secret_value = get_parameter("/path/to/parameter", transform="json")
    return {"statusCode": 200, "body": f"Fetched secret: {secret_value}"}

This example fetches a JSON-formatted parameter and caches it, reducing retrieval time for subsequent requests.


6. Handling ALB Events with ALBResolver

The ALBResolver utility simplifies handling ALB events, providing a lightweight routing framework and structured request handling.

from aws_lambda_powertools.event_handler import ALBResolver
from aws_lambda_powertools import Logger
 
logger = Logger()
app = ALBResolver()
 
@app.get("/hello")
def get_hello():
    return {"statusCode": 200, "body": "Hello from ALB"}
 
@app.post("/data")
def handle_data():
    # Process incoming POST request data
    return {"statusCode": 201, "body": "Data processed"}
 
@logger.inject_lambda_context
def lambda_handler(event, context):
    return app.resolve(event, context)

Explanation:

  • ALBResolver routes requests based on HTTP method and path, making it easy to handle different endpoints (/hello, /data) with minimal boilerplate.
  • @app.get("/hello") and @app.post("/data") map to specific routes and HTTP methods.
  • The app.resolve(event, context) in lambda_handler dispatches requests to the correct handler based on the ALB event.