NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #997 most downloaded on PyPI
Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity.
Last release 11 days ago
15 Sep 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 58 of the last 60 stable releases
3 versions withdrawn
withdrawn after publishing
7 years old
530 releases · first in 2019
Nothing published for this version
Nothing published for this version
Nothing published for this version
We're excited to announce Batch resolvers in GraphQL Event Handler to tackle the infamous N+1 problem in GraphQL 💪, making it easier to work with batc
One column per quarter.
We're excited to announce Batch resolvers in GraphQL Event Handler to tackle the infamous N+1 problem in GraphQL 💪, making it easier to work with batching in AWS AppSync.
Thanks to @danieljnchen, the validation utility now supports referencing internal schemas within your JSON files. 🌟
🌟 ⭐ A big thank you to our new contributors: @scampbell5, @matteofigus, and @danieljnchen.
You can now use a batch resolver to handle batch requests coming from AWS AppSync. This is useful when AWS AppSync has batching enabled for Lambda Resolvers as it allows the aggregation of as many requests as possible before invoking your AWS Lambda function, effectively solving the N+1 problem in GraphQL.
You can now control JSON schema references with custom handlers. This is useful when you might want to optimize caching, reducing HTTP calls, or fetching them from non-HTTP endpoints.
Last but not least, @scampbell5 helps us fix the types for partition and offset in the KafkaEventRecord Event Source Data Class.
96abcbb to 257eca8 in /docs (#4540) by @dependabot@danieljnchen, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @matteofigus, @mploski, @ran-isenberg and @scampbell5
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
The regression issue caused by PR https://github.com/aws-powertools/powertools-lambda-python/pull/4421 is resolved in this patch release. The issue oc
The regression issue caused by PR https://github.com/aws-powertools/powertools-lambda-python/pull/4421 is resolved in this patch release. The issue occurred due to static typing importing Pydantic, as it went undetected in our pipeline and code review.
To prevent from happening again, we will introduce dynamic tests for all optional dependencies. We will pause new releases until that is implemented and verified. For further improvement, we will look into making daily pre-releases to help create more complex canary tests.
@github-actions, @github-actions[bot] and @leandrodamascena
This release improves Event Handler with (a) better serialization error for unsupported data types, and (b) middlewares are now triggered when a route
This release improves Event Handler with (a) better serialization error for unsupported data types, and (b) middlewares are now triggered when a route is not found (404). We also crushed OpenAPI bugs for a smoother experience 🪲.
Thanks to @knightmre, Event Source Data Classes now features (a) updates Cognito User Pool User Migration event with verification link, and (b) new Pre-token generation and custom sender events.
🌟 ⭐ A big thank you to our new contributors: @knightmre, @phipag, @keithrozario, and @stevenhoelscher.
You can now run middlewares even when a route is not found. Before, Event Handler immediately returned a HTTP 404 (Not Found). However, we learned from customers that key middleware logic should always run regardless, hence the fix.
This allows you to consistently perform cross-cutting concerns like logging, header injection, authorization, etc. even for invalid routes.
You can now use CloudFormationCustomResourceEvent for a better experience with type hinting and code completion support.
NOTE. We recommend customers to use CloudFormation Custom Resource Helper library to author custom resources.
We now raise a SerializationError when trying to serialize unsupported data types. Before, Event Handler did not distinguish between unsupported type or object altogether, like SQLAlchemy models.
You can bring your own custom serializer for additional data type support.
Last but not least, we fixed an issue that occurred when disabling Idempotency using an environment variable. Thanks to @stevenhoelscher for this great catch.
8a87f05 to 96abcbb in /docs (#4461) by @dependabot5358893 to 8a87f05 in /docs (#4408) by @dependabot48d1914 to 5358893 in /docs (#4377) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @keithrozario, @knightmre, @leandrodamascena, @phipag and @stevenhoelscher
A regression issue caused by PR 4295 has been resolved in this release. The issue occurred when using multiple instances of the Logger in different fi
A regression issue caused by PR 4295 has been resolved in this release. The issue occurred when using multiple instances of the Logger in different files and with the same Logger name.
🌟 ⭐ Thank you @Thomas-McKanna, @SimonBFrank, @saravsak, and @JacobAuthenic for quickly identifying and helping to resolve this regression.
@leandrodamascena
This release introduces a handy new decorator for HTTP HEAD verb in Event Handler, improving the developer experience. Additionally, it offers a strai
This release introduces a handy new decorator for HTTP HEAD verb in Event Handler, improving the developer experience. Additionally, it offers a straightforward way to persist authorization sessions in OpenAPI, enhancing convenience. 🚀🚀 As always, we've fixed some bugs and refined our documentation. 🎉
🌟 ⭐ Huge thanks to our new contributors: @raymondbutcher, @nlykkei, and @keithrozario!
We've introduced a new @app.head decorator to the Event Handler, as it's the recommended approach when you only need to return headers in the response content.
We've added support to persist authorization data, such as OAuth 2.0 access tokens, even when the browser is closed or refreshed. This ensures that the user's authorization information is securely retained in the browser's local storage, providing a seamless experience and avoiding the need to re-authenticate.
48d1914 to 5358893 in /docs (#4377) by @dependabot8ef47d7 to 48d1914 in /docs (#4336) by @dependabot11d7ec0 to 8ef47d7 in /docs (#4323) by @dependabot98c9809 to 11d7ec0 in /docs (#4269) by @dependabote309089 to 98c9809 in /docs (#4236) by @dependabot521644b to e309089 in /docs (#4216) by @dependabot@Wurstnase, @benjamingorman, @dependabot, @dependabot[bot], @dreamorosi, @github-actions, @github-actions[bot], @heitorlessa, @keithrozario, @leandrodamascena, @nlykkei, @phipag, @raymondbutcher and @rubenfonseca
chore(ci): prevent deprecated custom runner from being used (#4061) by @heitorlessa
This release adds Security Schemes support for generated OpenAPI / Swagger UI, and a new feature to manipulate idempotent responses. 🚀🚀 And of course, you know it, fixes in typing and documentation. 🎉
🌟 Tons of things in this release was only possible because of our community. 🌟 A huge thank you to @walmsles, @Wurstnase, @SZubarev, @Emerson-MM-Filho, @nlykkei, @amyc92 and many others for your support and collaboration!
You can now add security scheme annotations to your generated OpenAPI documentation (HTTP headers, API keys, OAuth 2 and OpenID connect). Additionally, you can configure the built-in Swagger UI to use OAuth 2 when generating requests.
🌟 Huge thanks to @nlykkei for helping us shape this feature!
You can now set up a response_hook in the IdempotentConfig class to manipulate the returned data when an operation is idempotent. The hook function will be called with the current deserialized response object and the idempotency record.
This can be used for changing something in the response, inject headers, emit custom metrics, and many other use cases.
🌟 Thank you @walmsles for leading the design and implementation of this!
6b124e1 to 521644b in /docs (#4141) by @dependabot065f3af to 6b124e1 in /docs (#4055) by @dependabot3307665 to 065f3af in /docs (#4052) by @dependabot@Emerson-MM-Filho, @SZubarev, @Wurstnase, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @rubenfonseca and @walmsles
We're excited to introduce some significant new features and improvements in this release:
We're excited to introduce some significant new features and improvements in this release:
We also made enhancements to our OpenAPI and type checking, and fixed some bugs!
⭐ Huge thanks to our new contributors: @rafrafek, @xquek, and @par6n!
In response to our customer requests, Powertools now provides an enhanced experience for effortlessly creating and updating Parameters and Secrets. Recognizing the critical importance of parameters and secrets management, we created this new feature to empower customers with a seamless experience in managing their sensitive information.
A big thank you to @stephenbawks for their dedicated effort in implementing this new feature.
Some customers may need to create metrics with specific timestamps, to address this use case we've added the capability set custom metrics with specific timestamps to improve customer flexibility. Previously, this was not possible and all metrics were generated with the current timestamp.
We've created a new flag to enable seamless processing of messages from different group IDs. Activating this flag ensures that messages from a failed group ID are returned to SQS, allowing uninterrupted processing of messages from subsequent group IDs.
Thank you @duc00, for highlighting such an important matter and contributing to the improvement of this utility.
Customers now have the ability to utilize CloudWatchAlarmEvent, which provides Type hinting and code completion support for this event, enhancing the development experience.
Last but not least, we've made significant improvements to our OpenAPI utility and fixed bugs to ensure a smoother experience. See all the latest improvements and bugfix in the changes section.
6c81a89 to 3307665 in /docs (#4017) by @dependabot3678304 to 6c81a89 in /docs (#3973) by @dependabot@TonySherman, @dependabot, @dependabot[bot], @eldritchideen, @github-actions, @github-actions[bot], @leandrodamascena, @par6n, @rafrafek, @rubenfonseca, @stephenbawks and @xquek
This patch release squashes a couple of bugs:
This patch release squashes a couple of bugs:
Huge thanks to @aitchnyu, @robk1234 and @palfrey for reporting and helping us fix these issues!
Changes
🐛 Bug and hot fixes
🔧 Maintenance
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @rubenfonseca
We’re super excited to introduce a brand new utility to author Agents for Amazon Bedrock! 🎉🎉
We’re super excited to introduce a brand new utility to author Agents for Amazon Bedrock! 🎉🎉
Agents for Amazon Bedrock is a feature to build and deploy conversational agents that can interact with your customers using Large Language Models (LLM) and AWS Lambda functions.
Building on top of the Event Handler validation framework and the OpenAPI generation feature introduced in December, we created a new utility to:
Here's an agent with an action to schedule a meeting, ensuring that a valid email was passed in by the user:
Check out our brand new docs on the feature and let us know what you think!
Oh and we also fixed some bugs :) Thank you @kbakk and @aminalaee for your contributions!
49d1bfd to 7be068b in /docs (#3872) by @dependabot43b898a to 49d1bfd in /docs (#3857) by @dependabot@aminalaee, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @rubenfonseca
This patch release removes Data Masking dependencies from our managed Lambda Layer, explicitly aws-encryption-sdk who depend on cffi. The issue is tha
This patch release removes Data Masking dependencies from our managed Lambda Layer, explicitly aws-encryption-sdk who depend on cffi. The issue is that cffi has to be compiled to each specific Python version while we didn't.
We are investigating the creation of a new layer per each Python version to bring back Data Masking dependencies. As of now, to use Data masking, you'll need to bring aws-encryption-sdk as part of your dependencies until then.
@TonySherman, @Wurstnase, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa and @leandrodamascena
Patch release to fix a regression introduced in v2.33 when running Event Handler REST API locally _(unit test)_...spotted by @jonathan-Chang 🌟!
Patch release to fix a regression introduced in v2.33 when running Event Handler REST API locally (unit test)...spotted by @jonathan-Chang 🌟!
Huge thanks to Jonathan for reporting on Discord and helping triage all the way through.
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @heitorlessa
This release adds a new list intersection set of actions in Feature Flags, hot new community content, and tons of bugs squashed!
This release adds a new list intersection set of actions in Feature Flags, hot new community content, and tons of bugs squashed!
🌟 Huge thanks to community friends (recurring contributors): @gwlester on new feature flag list intersection, @ericbn on docs layer ARN automation bug, and @ran-isenberg on two hot new content!
Thanks to @Rogalek for the feature request!
You can now toggle feature flags on three new actions:
ALL_IN_VALUE. Toggle a given flag if all list items provided are also available in the schema.
<details> <summary>Schema sample</summary>
{
"my_feature": {
"default": false,
"rules": {
"tenant_id is in allowed list": {
"when_match": true,
"conditions": [
{
"action": "ALL_IN_VALUE",
"key": "tenant_id",
"value": [
"Łukasz",
"Gerald",
"Leandro",
"Heitor"
]
}
]
}
}
}
}
</details>
ANY_IN_VALUE. Toggle a given flag if any list item provided is also available in the schema.
<details> <summary>Schema sample</summary>
{
"my_feature": {
"default": false,
"rules": {
"tenant_id is in allowed list": {
"when_match": true,
"conditions": [
{
"action": "NONE_IN_VALUE",
"key": "tenant_id",
"value": [
"Łukasz",
"Gerald",
"Leandro",
"Heitor"
]
}
]
}
}
}
}
</details>
NONE_IN_VALUE. Toggle a given flag is no list item provided is available in the schema.
<details> <summary>Schema sample</summary>
{
"my_feature": {
"default": false,
"rules": {
"tenant_id is in allowed list": {
"when_match": true,
"conditions": [
{
"action": "NONE_IN_VALUE",
"key": "tenant_id",
"value": [
"Łukasz",
"Gerald",
"Leandro",
"Heitor"
]
}
]
}
}
}
}
</details>
62d3668 to 43b898a in /docs (#3801) by @dependabot6a72238 to 62d3668 in /docs (#3756) by @dependabot62d3668 to 43b898a in /docs (#3801) by @dependabot6a72238 to 62d3668 in /docs (#3756) by @dependabot@dependabot, @dependabot[bot], @dreamorosi, @ericbn, @github-actions, @github-actions[bot], @gwlester, @heitorlessa, @hjgraca, @ran-isenberg and @rubenfonseca
This release officially drops support for Python 3.7 in Powertools for AWS, followed by AWS Lambda runtime deprecation. We also published our versioni…
This release officially drops support for Python 3.7 in Powertools for AWS, followed by AWS Lambda runtime deprecation. We also published our versioning policy under Processes section to give you further transparency.
🌟 Huge thanks to a new contributor @Wurstnase (mypy fix)
🔥 Nathan Hanks's new blog post features how he used the Metrics feature to boost app engagement
e0d6c67 to 6a72238 in /docs (#3735) by @dependabota4a2029 to e0d6c67 in /docs (#3708) by @dependabote0d6c67 to 6a72238 in /docs (#3735) by @dependabota4a2029 to e0d6c67 in /docs (#3708) by @dependabot@Wurstnase, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena and @ran-isenberg
We are pleased to announce our first security feature: Data Masking. You can now encrypt, decrypt, or irreversibly erase sensitive information to prot
We are pleased to announce our first security feature: Data Masking. You can now encrypt, decrypt, or irreversibly erase sensitive information to protect data confidentiality.
We also made enhancements to our OpenAPI utility, and fixed some bugs!
⭐ Huge thanks to our new contributor: @maauk
You can now encrypt, decrypt, or irreversibly erase sensitive information to protect data confidentiality.
We partnered with the AWS Crypto team to offer a thin layer on top of the AWS Encryption SDK and Amazon KMS, optimized to run on AWS Lambda ephemeral environments.
At launch, Data Masking solves three common use cases, with a fourth one (field encryption) coming.
It wouldn't be awesome if we didn't mention that we spent a few months crafting several code snippets, use cases, diagrams, and a simplified terminology to help you digest common industry security practices.
Enough with the talk :) Here's a working code snippet with these use cases combined.
from __future__ import annotations
import os
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.data_masking import DataMasking
from aws_lambda_powertools.utilities.data_masking.provider.kms.aws_encryption_sdk import (
AWSEncryptionSDKProvider,
)
from aws_lambda_powertools.utilities.typing import LambdaContext
KEY_ONE = os.getenv("KMS_KEY_ARN", "")
KEY_TWO = os.getenv("KMS_KEY_TWO_ARN", "")
logger = Logger()
encryption_provider = AWSEncryptionSDKProvider(keys=[KEY_ONE, KEY_TWO]) # encrypt/decrypt operations
data_masker = DataMasking(provider=encryption_provider)
@logger.inject_lambda_context
def lambda_handler(event: dict, context: LambdaContext) -> dict:
data: dict = event.get("body", {})
logger.info("Erasing fields email, address.street, and company_address")
erased: dict = data_masker.erase(data, fields=["email", "address.street", "company_address"]) # values become '*****'
# tenant_id being optional metadata that must match in decrypt for further protection
encrypted: str = data_masker.encrypt(data, tenant_id=event.get("tenant_id", ""))
decrypted: dict = data_masker.decrypt(data, tenant_id=event.get("tenant_id", ""))
return erased
⭐⭐ Huge thanks to @seshubaws for the extensive work on this feature!
Our enhanced OpenAPI utility now enables you to seamlessly incorporate headers into your API specifications.
from typing import List
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.event_handler.openapi.params import Header
from aws_lambda_powertools.shared.types import Annotated
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver(enable_validation=True)
@app.get("/hello")
def get_hello(header2: Annotated[List[str], Header()], header1: Annotated[str, Header()]):
print(header2)
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
9aad7af to a4a2029 in /docs (#3679) by @dependabot58eef6c to 9aad7af in /docs (#3670) by @dependabot9aad7af to a4a2029 in /docs (#3679) by @dependabot58eef6c to 9aad7af in /docs (#3670) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @leandrodamascena, @maauk and @seshubaws
docs(homepage): add banner about Python 3.7 deprecation (#3618) by @leandrodamascena
We're excited to introduce two significant new features in our Idempotency utility:
We also made enhancements to our OpenAPI and Event Sources utilities, and fixed some bugs!
⭐ Huge thanks to our new contributors: @sbailliez, @Thomas-McKanna, and @dastra!
You can now seamlessly switch between DynamoDB and Redis as a persistence storage layer. This allows you to leverage the Idempotency utility in previously unavailable scenarios, such as handling responses over 400kb.
We remain committed to making efforts to introduce new backends, and we would love to hear from you on which backend we should prioritize next!
⭐ ⭐ Huge thanks to @roger-zhangg for your help!
AWS has recently introduced support for ReturnValuesOnConditionCheckFailure, a feature designed to streamline conditional write operations and reducing costs in Amazon DynamoDB. With this enhancement, Powertools for AWS Lambda now optimistically attempts to write items to DynamoDB. If the item already exists, it seamlessly returns it from DynamoDB without requiring an additional operation.
S3 Batch Operations are now supported on the Event Source utility. When using S3 Batch Operations, a Lambda function can be used to execute various operations. For each task, you can choose to either:
A) Return the task as a success (default) B) Return the task as temporarily failed (e.g., due to a timeout when connecting to other services) and enable automatic retries. C) Return the task as permanently failed, resulting in job failure.
This example illustrates how you can return different status based on your specific execution logic.
You can now define additional response models within the OpenAPI schema utility, allowing you to leverage existing Pydantic data models and classes.
Last but not least, you can now effortlessly download the OpenAPI schema file directly from the SwaggerUI.
2f29d71 to 58eef6c in /docs (#3633) by @dependabot2f29d71 to 58eef6c in /docs (#3633) by @dependabot@Thomas-McKanna, @dastra, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @leandrodamascena, @roger-zhangg, @rubenfonseca and @sbailliez
This release introduces enhanced top-level Tags in the OpenAPI schema, and adds Lambda layer support in AWS Canada region (ca-west-1). It also include
This release introduces enhanced top-level Tags in the OpenAPI schema, and adds Lambda layer support in AWS Canada region (ca-west-1). It also includes improvements to documentation and bug fixes.
⭐ Huge thanks to our new contributors: @kamilturek (Middleware factory docs), and @troyswanson (Parameters).
Docs: Event Handler OpenAPI
The OpenAPI schema now supports more comprehensive top-level Tags, simplifying the organization and categorization of API operations.
Last but not least, kudos to @Mavtti for bringing attention to an issue in our error handling within the Parser utility, thereby improving the development experience.
9af3b7e to 2f29d71 in /docs (#3559) by @dependabot9af3b7e to 2f29d71 in /docs (#3559) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @kamilturek, @leandrodamascena, @rubenfonseca and @troyswanson
This patch release fixes three bugs related to the OpenAPI and Swagger features:
This patch release fixes three bugs related to the OpenAPI and Swagger features:
⭐ Huge thanks to @MCR2019 and @danikenan for reporting those issues! ⭐
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @rubenfonseca
This patch release fixes a bug when using the event handler Router together with OpenAPI metadata.
This patch release fixes a bug when using the event handler Router together with OpenAPI metadata.
Huge thanks to @MCR2019 for finding and reporting this out!
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @rubenfonseca
This release follows the newly announced Python 3.12 runtime in AWS Lambda 🚀
This release follows the newly announced Python 3.12 runtime in AWS Lambda 🚀
876b39c to 9af3b7e in /docs (#3486) by @dependabot876b39c to 9af3b7e in /docs (#3486) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena and @rubenfonseca
This patch release fixes a bug in the Logger utility, ensuring it prints non-ASCII values as-is instead of escaping them. Previously, non-ASCII charac
This patch release fixes a bug in the Logger utility, ensuring it prints non-ASCII values as-is instead of escaping them. Previously, non-ASCII characters were displayed in an encoded format.
Huge thanks to @bml1g12 for reporting this! :star:
876b39c to 9af3b7e in /docs (#3486) by @dependabot20241c6 to 876b39c in /docs (#3477) by @dependabot8c72011 to 20241c6 in /docs (#3470) by @dependabot876b39c to 9af3b7e in /docs (#3486) by @dependabot20241c6 to 876b39c in /docs (#3477) by @dependabot8c72011 to 20241c6 in /docs (#3470) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @heitorlessa
Standardized Retrieval of API Gateway Authorizer Context
Standardized Retrieval of API Gateway Authorizer Context
This release standardizes how to retrieve the API Gateway authorizer context in both v1 and v2 of the Lambda handler. Previously, there were inconsistencies in how customers retrieved authorization context between V1 and V2 payloads.
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools import Logger
app = APIGatewayRestResolver()
logger = Logger(level="INFO")
@app.get("/")
def initialize():
context: dict = app.current_event.request_context.authorizer.get_context()
logger.info(context.get("tenantId"))
def lambda_handler(event, context):
return app.resolve(event, context)
We also fixed an issue with dependency injection when using decorators in the Lambda handler function. Previously, dependencies were not properly injected when decorators were present, leading to runtime errors.
fc42bac to 8c72011 in /docs (#3416) by @dependabotfc42bac to 8c72011 in /docs (#3416) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena and @sthulb
This patch release fixes a bug on the event handler utility, where using the compress option was causing an error.
This patch release fixes a bug on the event handler utility, where using the compress option was causing an error.
Huge thanks to @dacianf for reporting this!
@github-actions, @github-actions[bot] and @rubenfonseca
This release adds support for Data Validation and automatic OpenAPI generation in Event Handler.
This release adds support for Data Validation and automatic OpenAPI generation in Event Handler.
Even better, it works with your existing resolver (API Gateway REST/HTTP, ALB, Lambda Function URL, VPC Lattice)!
Did you read that correctly? Yes, you did! Look at this:
Docs: Data validation
By adding enable_validation=True to your resolver constructor, you’ll change the way the resolver works. We will:
This moves data validation responsibilities to Event Handler resolvers, reducing a ton of boilerplate code. You can now focus on just writing your business logic, and leave the validation to us!
from typing import List, Optional
import requests
from pydantic import BaseModel, Field
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext
tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver(enable_validation=True)
class Todo(BaseModel):
userId: int
id_: Optional[int] = Field(alias="id", default=None)
title: str
completed: bool
@app.post("/todos")
def create_todo(todo: Todo) -> str:
response = requests.post("https://jsonplaceholder.typicode.com/todos", json=todo.dict(by_alias=True))
response.raise_for_status()
return response.json()["id"]
@app.get("/todos")
@tracer.capture_method
def get_todos() -> List[Todo]:
todo = requests.get("https://jsonplaceholder.typicode.com/todos")
todo.raise_for_status()
return todo.json()
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Docs: OpenAPI generation
When you enable data validation, we automatically inspect your API in a way that makes it possible to generate OpenAPI specifications automatically!
You can export the OpenAPI spec for customization, manipulation, merging micro-functions, etc., in two ways:
app.get_openapi_schema()app.get_openapi_json_schema()Here’s one way to print the schema if you were to run your Python Lambda handler locally:
import requests
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.event_handler.openapi.models import Contact, Server
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver(enable_validation=True)
@app.get("/todos/<todo_id>")
def get_todo_title(todo_id: int) -> str:
todo = requests.get(f"https://jsonplaceholder.typicode.com/todos/{todo_id}")
todo.raise_for_status()
return todo.json()["title"]
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
if __name__ == "__main__":
print(
app.get_openapi_json_schema(
title="TODO's API",
version="1.21.3",
summary="API to manage TODOs",
description="This API implements all the CRUD operations for the TODO app",
tags=["todos"],
servers=[Server(url="https://stg.example.org/orders", description="Staging server")],
contact=Contact(name="John Smith", email="john@smith.com"),
),
)
Can you see where this is going? Keep reading :)
Docs: Swagger UI
Last but not least... you can now enable an embedded Swagger UI to visualize and interact with your newly auto-documented API!
from typing import List, Optional
import requests
from pydantic import BaseModel, Field
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver(enable_validation=True)
app.enable_swagger() # by default, path="/swagger"
@app.get("/todos")
@tracer.capture_method
def get_todos() -> List[Todo]:
todo = requests.get("https://jsonplaceholder.typicode.com/todos")
todo.raise_for_status()
return todo.json()
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
The Swagger UI appears by default at the /swagger path, but you can customize this to serve the documentation from another path, and specify the source for Swagger UI assets.
We can’t wait for you try this new features!
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, and @rubenfonseca
This patch release addresses the following issues:
This patch release addresses the following issues:
Logger.addFilter/removeFilter*/*) binary types when CORS is configured@logger.inject_lambda_context("powertools_json(body).my_field")🌟 Big thanks to @rafrafek and @martinber for their critical eye in spotting some of these issues
2c57e4d to fc42bac in /docs (#3375) by @dependabotf486dc9 to 2c57e4d in /docs (#3366) by @dependabot2c57e4d to fc42bac in /docs (#3375) by @dependabotf486dc9 to 2c57e4d in /docs (#3366) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa and @leandrodamascena
This minor release adds support for two new environments variables to configure the log level in Logger.
This minor release adds support for two new environments variables to configure the log level in Logger.
You can now configure the log level of for Logger using two new environment variables: AWS_LAMBDA_LOG_LEVEL and POWERTOOLS_LOG_LEVEL.
The new environment variables will work along the existing LOG_LEVEL variable that is now considered legacy and will be removed in the future.
Setting the log level now follows this order:
AWS_LAMBDA_LOG_LEVEL environment variablelevel constructor option, or by calling the logger.setLevel() methodPOWERTOOLS_LOG_LEVEL environment variable@dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @leandrodamascena
This patch release fixes a regression when using prefix stripping with middlewares on the event handler. It also fixes a mistyped field on the Kinesis
This patch release fixes a regression when using prefix stripping with middlewares on the event handler. It also fixes a mistyped field on the Kinesis Firehose event source, and a problem when getting multiple encrypted SSM parameters.
Huge thanks to @roger-zhangg and @sean-hernon for helping us identifying and fixing these issues.
772e14e to f486dc9 in /docs (#3299) by @dependabotdf9409b to 772e14e in /docs (#3265) by @dependabotcb38dc2 to df9409b in /docs (#3216) by @dependabot772e14e to f486dc9 in /docs (#3299) by @dependabotdf9409b to 772e14e in /docs (#3265) by @dependabotcb38dc2 to df9409b in /docs (#3216) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @jvnsg, @leandrodamascena, @roger-zhangg, @rubenfonseca and @sean-hernon
This release adds richer exception details to the logger utility, support for [VPC Lattice Payload V2](https://docs.aws.amazon.com/lambda/latest/dg/se
This release adds richer exception details to the logger utility, support for VPC Lattice Payload V2, smarter model inference in the parser utility, expanded ARM64 Lambda Layer support on additional regions, and fixes some bugs!
⭐ Huge thanks to our new contributors: @Tom01098, @stevrobu, and @pgrzesik!
Docs: logger
The logger utility now logs exceptions in a structured format to simplify debugging. Previously, exception tracebacks appeared as a single string containing the raw stack trace frames. Developers had to parse each frame manually to extract file names, line numbers, function names, etc.
With the new serialize_stacktrace flag, the logger prints stack traces as structured JSON. This clearly surfaces exception details like filenames, lines, functions, and statements per frame. The structured output eliminates the need to parse traceback strings, improving observability and accelerating root cause analysis.
Docs: event handler, parser
Amazon VPC Lattice is a fully managed application networking service that you use to connect, secure, and monitor the services for your application across multiple accounts and virtual private clouds (VPC). You can register your Lambda functions as targets with a VPC Lattice target group, and configure a listener rule to forward requests to the target group for your Lambda function.
With this seamless integration, you can now leverage the performance benefits of Amazon VPC Lattice Payload V2 directly in your event handlers. The latest release enables handling Lattice events using the familiar event handler API you already know, including critical features like CORS support and response serialization.
Docs: parser
The event_parser decorator previously required you to duplicate the type when using type hints. Now, the event_parser decorator can infer the event type directly from your handler signature. This avoids having to redeclare the type in the event_parser decorator.
a4cfa88 to cb38dc2 in /docs (#3189) by @dependabotcbfecae to a4cfa88 in /docs (#3175) by @dependabote5f28aa to cbfecae in /docs (#3157) by @dependabot06673a1 to e5f28aa in /docs (#3134) by @dependabotb41ba6d to 06673a1 in /docs (#3124) by @dependabota4cfa88 to cb38dc2 in /docs (#3189) by @dependabotcbfecae to a4cfa88 in /docs (#3175) by @dependabote5f28aa to cbfecae in /docs (#3157) by @dependabot06673a1 to e5f28aa in /docs (#3134) by @dependabotb41ba6d to 06673a1 in /docs (#3124) by @dependabot@Tom01098, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @rubenfonseca, @pgrzesik, @roger-zhangg, @seshubaws, @stephenbawks and @stevrobu
This is a patch release to address a bug in @metrics.log_metrics decorator to support functions with arbitrary arguments/kwargs, and a minor typing fi
This is a patch release to address a bug in @metrics.log_metrics decorator to support functions with arbitrary arguments/kwargs, and a minor typing fix in Logger for explicit None return types.
🌟 Huge thanks to two new contributors who reported and fixed both bugs @FollowTheProcess and @thegeorgeliu
4ff781e to b41ba6d in /docs (#3117) by @dependabotc4890ab to 4ff781e in /docs (#3110) by @dependabot4ff781e to b41ba6d in /docs (#3117) by @dependabotc4890ab to 4ff781e in /docs (#3110) by @dependabot@FollowTheProcess, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot] and @thegeorgeliu
This release simplifies data transformation with Amazon Kinesis Data Firehose, and handling secret rotation events from Amazon Secrets Manager.
This release simplifies data transformation with Amazon Kinesis Data Firehose, and handling secret rotation events from Amazon Secrets Manager.
🌟 Huge welcome to our new contributor @TonySherman. Tony documented how to use Event Handler with micro Lambda functions.
When using Kinesis Firehose, you can use a Lambda function to perform data transformation. For each transformed record, you can choose to either:
To make this process easier, you can now use KinesisFirehoseDataTransformationResponse and serialization functions to quickly encode payloads into base64 data for the stream.
Example where you might want to drop unwanted records from the stream.
from json import JSONDecodeError
from typing import Dict
from aws_lambda_powertools.utilities.data_classes import (
KinesisFirehoseDataTransformationRecord,
KinesisFirehoseDataTransformationResponse,
KinesisFirehoseEvent,
event_source,
)
from aws_lambda_powertools.utilities.serialization import base64_from_json
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=KinesisFirehoseEvent)
def lambda_handler(event: KinesisFirehoseEvent, context: LambdaContext):
result = KinesisFirehoseDataTransformationResponse()
for record in event.records:
try:
payload: Dict = record.data_as_json # decodes and deserialize base64 JSON string
## generate data to return
transformed_data = {"tool_used": "powertools_dataclass", "original_payload": payload}
processed_record = KinesisFirehoseDataTransformationRecord(
record_id=record.record_id,
data=base64_from_json(transformed_data),
)
except JSONDecodeError:
# our producers ingest JSON payloads only; drop malformed records from the stream
processed_record = KinesisFirehoseDataTransformationRecord(
record_id=record.record_id,
data=record.data,
result="Dropped",
)
result.add_record(processed_record)
# return transformed records
return result.asdict()
When rotating secrets with Secrets Manager, it invokes your Lambda function in four potential steps:
createSecret. Create a new version of the secret.setSecret. Change the credentials in the database or service.testSecret. Test the new secret version.finishSecret. Finish the rotation.You can now use SecretsManagerEvent to more easily access the event structure, and combine Parameters to get secrets to perform secret operations.
from aws_lambda_powertools.utilities import parameters
from aws_lambda_powertools.utilities.data_classes import SecretsManagerEvent, event_source
secrets_provider = parameters.SecretsProvider()
@event_source(data_class=SecretsManagerEvent)
def lambda_handler(event: SecretsManagerEvent, context):
# Getting secret value using Parameter utility
# See https://docs.powertools.aws.dev/lambda/python/latest/utilities/parameters/
secret = secrets_provider.get(event.secret_id, VersionId=event.version_id, VersionStage="AWSCURRENT")
if event.step == "setSecret":
# Perform any secret rotation logic, e.g., change DB password
# Check more examples: https://github.com/aws-samples/aws-secrets-manager-rotation-lambdas
print("Rotating secret...")
return secret
dd1770c to c4890ab in /docs (#3078) by @dependabotdd1770c to c4890ab in /docs (#3078) by @dependabot@TonySherman, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @roger-zhangg and @sthulb
This release brings custom serialization/deserialization to Idempotency, and Middleware support in Event Handler (API Gateway REST/HTTP, ALB, Lambda F
This release brings custom serialization/deserialization to Idempotency, and Middleware support in Event Handler (API Gateway REST/HTTP, ALB, Lambda Function URL, VPC Lattice). Oh didn't I say some bug fixes too? 🙏
🌟 Big welcome to the new contributors: @adriantomas, @aradyaron, @nejcskofic, @waveFrontSet
Docs 🌟 Huge thanks to @aradyaron!!
Previously, any function annotated with @idempotent_function will have its return type as a JSON object - this was challenging for customers using Pydantic, Dataclasses, or any custom types.
You can now use output_serializer to automatically serialize the return type for Dataclasses or Pydantic, and bring your own serializer/deserializer too!
from aws_lambda_powertools.utilities.idempotency import (
DynamoDBPersistenceLayer,
IdempotencyConfig,
idempotent_function,
)
from aws_lambda_powertools.utilities.idempotency.serialization.pydantic import PydanticSerializer
from aws_lambda_powertools.utilities.parser import BaseModel
from aws_lambda_powertools.utilities.typing import LambdaContext
dynamodb = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
config = IdempotencyConfig(event_key_jmespath="order_id") # see Choosing a payload subset section
class OrderItem(BaseModel):
sku: str
description: str
class Order(BaseModel):
item: OrderItem
order_id: int
class OrderOutput(BaseModel):
order_id: int
@idempotent_function(
data_keyword_argument="order",
config=config,
persistence_store=dynamodb,
output_serializer=PydanticSerializer,
)
# order output is inferred from return type
def process_order(order: Order) -> OrderOutput:
return OrderOutput(order_id=order.order_id)
def lambda_handler(event: dict, context: LambdaContext):
config.register_lambda_context(context) # see Lambda timeouts section
order_item = OrderItem(sku="fake", description="sample")
order = Order(item=order_item, order_id=1)
# `order` parameter must be called as a keyword argument to work
process_order(order=order)
Docs 🌟 Huge thanks to @walmsles for the implementation and marvelous illustrations!!
<img width="1088" alt="image" src="https://github.com/aws-powertools/powertools-lambda-python/assets/3340292/5f8b9359-3faa-4d06-a067-6bda99a5959b">
You can now bring your own middleware to run logic before or after requests when using Event Handler.
The goal continues to be having built-in features over middlewares, so you don't have to own boilerplate code. That said, we recognize we can't virtually cover every use case - that's where middleware comes in!
Example using per-route and global middlewares
import middleware_global_middlewares_module
import requests
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response
app = APIGatewayRestResolver()
logger = Logger()
app.use(middlewares=[middleware_global_middlewares_module.log_request_response])
@app.get("/todos", middlewares=[middleware_global_middlewares_module.inject_correlation_id])
def get_todos():
todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos.raise_for_status()
return {"todos": todos.json()[:10]}
@logger.inject_lambda_context
def lambda_handler(event, context):
return app.resolve(event, context)
f4764d1 to dd1770c in /docs (#3044) by @dependabotb1f7f94 to f4764d1 in /docs (#3031) by @dependabot97da15b to b1f7f94 in /docs (#3021) by @dependabotf4764d1 to dd1770c in /docs (#3044) by @dependabotb1f7f94 to f4764d1 in /docs (#3031) by @dependabot97da15b to b1f7f94 in /docs (#3021) by @dependabot@adriantomas, @aradyaron, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @nejcskofic, @walmsles and @waveFrontSet
This patch release primarily addresses a fix for customers who utilize default tags and metric-specific tags within the Datadog Metrics provider. Tags
This patch release primarily addresses a fix for customers who utilize default tags and metric-specific tags within the Datadog Metrics provider. Tags are now merged seamlessly, effectively resolving precedence conflicts that can arise when using tags with the same key.
The newly generated metric is now:
{
"m": "SuccessfulBooking",
"v": 1,
"e": 1692736997,
"t": [
"product:ticket"
"flight:AB123",
]
}
:star2: Huge thanks to @ecokes for reporting and reproducing it.
cd3a522 to 97da15b in /docs (#2987) by @dependabotcd3a522 to 97da15b in /docs (#2987) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @leandrodamascena and @rubenfonseca
This release adds the most requested feature ever: observability providers. You can now send custom metrics to Datadog using the same optimized develo
This release adds the most requested feature ever: observability providers. You can now send custom metrics to Datadog using the same optimized development experience Powertools for AWS Lambda offers.
Also, you can now use our provided Lambda Layer in the new AWS Israel region (il-central-1).
⭐ ⭐ Huge thanks to Petar Lishov and Roger Zhang for your help!
Three years ago, we launched Powertools for AWS Lambda Python, making it easier to instrument your code with distributed tracing (Tracer), structured logging (Logger), and custom metrics (Metrics).
With the community, we’ve grown way past Observability and into several best practices, including 16 major features integrating with 15+ AWS services.
Today, we couldn’t be happier to share what we’ve been working with the community for the last 4 months. You can now switch back and forth between CloudWatch EMF and Datadog for creating custom metrics, with minimal friction.
We will continue to develop our main integration with Amazon CloudWatch EMF and AWS X-Ray. That said, this release opens up possibilities for integrating with other AWS Lambda observability partners within Powertools for AWS Lambda.
We would love to hear from you on which observability provider we should prioritize next!
33e28bd to cd3a522 in /docs (#2859) by @dependabot33e28bd to cd3a522 in /docs (#2859) by @dependabot@aal80, @barreeeiroo, @dependabot, @dependabot[bot], @duc00, @github-actions, @github-actions[bot], @heitorlessa, @ivica-k, @leandrodamascena, @roger-zhangg and @royassis
This release follows the newly announced Python 3.11 runtime in AWS Lambda 🚀. It also adds a revamped Batch Processing documentation, along with numer
This release follows the newly announced Python 3.11 runtime in AWS Lambda 🚀. It also adds a revamped Batch Processing documentation, along with numerous bug fixes.
⭐ Huge thanks to new contributors: @94Sip and @duc00 for helping us improve Batch's documentation
This release adds a new error handling section, contextual information in key code snippets, and several new diagrams to improve understanding about Batch Processors and AWS Lambda Report Item Batch Failure feature.
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @ran-isenberg and @rubenfonseca
This offers you the flexibility to choose between Pydantic v1 and v2 with no breaking changes. This 3-week significant effort wouldn’t be possible wit…
We are happy to announce the official support for Pydantic V2. 🚀🚀🚀🚀
This offers you the flexibility to choose between Pydantic v1 and v2 with no breaking changes. This 3-week significant effort wouldn’t be possible without many Pydantic experts from our community, and the Pydantic team for fixing a regression - thank you!!
New public reference. A big thank you to @ovahal at Jit Security.
⭐ Huge thanks to our new contributor: @tinti!
Pydantic recently released version 2, bringing a plethora of exciting improvements and enhancements.
We did an extensive research on breaking changes between v1 and v2 to provide a smooth transition, when using Powertools for AWS Lambda (Python) Parser models and envelopes.
a28ed81 to 33e28bd in /docs (#2797) by @dependabota28ed81 to 33e28bd in /docs (#2797) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena and @tinti
chore(deps): migrate from retry to retry2 to address CVE-2022-42969 (#2665) by @heitorlessa
This release introduces signed and verifiable builds for PyPi, and a new documentation section to make our automation practices, maintainers playbook, and soon a re-imagined contributing guide more visible.
Love automation and CI/CD? We did an interview to walk through what's now documented under our new Automation section:
<img width="1692" alt="image" src="https://user-images.githubusercontent.com/3340292/253562585-96d256ce-ca78-4bf2-b247-6cfb2e3a0111.png">
As of today's release, you can now publicly verify our builds came from a trusted source to further strengthen supply chain security. We created a new Security section in our documentation with steps you can take to verify releases.
You can skip this part if you're not interested in the supply chain security space
For the past few months, we've been working hard to improve our operational and security posture. The biggest chunk of work was introducing Open Source Security Foundation (OSSF) Scorecard project to generate security health metrics, proactive security alerts, and attest we've been following OSSF Best Practices.
We couldn't be happier with the results.
Through the research, we've learned about SLSA as a framework to produce verifiable reproducible builds within our release pipeline. This enables our more security conscious customers to guarantee our releases came from this repository and every step can be publicly traced back.
Provenance step within our release pipeline to attest its reproducibility and authenticity
<img width="1689" alt="image" src="https://user-images.githubusercontent.com/3340292/253566521-d6681f2a-01ab-4e9c-84cb-cc56e4ec54ba.png">
3837c0f to a28ed81 in /docs (#2669) by @dependabot3837c0f to a28ed81 in /docs (#2669) by @dependabot@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @roger-zhangg, @step-security-bot and @sthulb
support for [Amazon VPC Lattice](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html) integrations
In this new release we added:
⭐ Huge thanks to our new contributor: @rafaelgsr!
Docs: event handler, parser
Amazon VPC Lattice is a fully managed application networking service that you use to connect, secure, and monitor the services for your application across multiple accounts and virtual private clouds (VPC). You can register your Lambda functions as targets with a VPC Lattice target group, and configure a listener rule to forward requests to the target group for your Lambda function.
We have added support for handling events from Amazon VPC Lattice in the event handler, using the same API as existing event handlers. This includes important functionalities like CORS support and response header serialization.
In addition, we added the corresponding Pydantic Parser model for the VPC Lattice event:
SQS events can encapsulate events originated in other AWS resources, such as S3 and SNS. To improve the experience when creating Lambda functions to handle those events, we created a new method to decoded those nested events easily. For instance, this is how you access the nested S3 event from an SQS event:
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @hjgraca, @leandrodamascena, @rafaelgsr, @ran-isenberg and @rubenfonseca
This release adds support for A/B testing in Feature Flags, and the ability to enable/disable compression for custom responses in Event Handler.
This release adds support for A/B testing in Feature Flags, and the ability to enable/disable compression for custom responses in Event Handler.
:star: Huge thanks to our new contributor: @ajwad-shaikh
You can now run experiments on a percentage of customers (e.g., A/B testing) with the new MODULE_RANGE action.
You can now enable GZIP compression with custom responses. This is useful when you only want to compress certain responses, or override compression for non-200 HTTP status code.
@ajwad-shaikh, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @hjgraca, @leandrodamascena and @sthulb
This release is full of new features and important bug fixes:
This release is full of new features and important bug fixes:
⭐ Huge thanks to new contributors: @abbasyadollahi @erikayao93 and @stephenbawks!
We now handle scenarios where the idempotency key might be optional by skipping the persistence storage layer operations (CRUD).
Here’s an example where uniqueness is dictated by X-Idempotency-Key header, but it might be optional:
Imagine we have three disctinct requests, where the headers key looks like this:
{"headers": {"X-Idempotency-Key": "7ca32179-f88f..."}}{"headers": {}}{"headers": {}}With this fix, the first request will follow the current idempotency mechanism while the second and third request will not trigger any idempotency mechanism to prevent unwanted side effects (e.g., idempotency key of None is hashed).
We made a significant change in the way routes are matched on the event handler by giving priority to the most specific routes.
Consider the following code:
With this fix, a GET request to /studies/fetch will now match the fetch_studies handler, even though it was declared last.
We made it easier to work with events comming from Amazon VPC Lattice and AWS Config Rules.
@abbasyadollahi, @dependabot, @dependabot[bot], @erikayao93, @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @ran-isenberg, @rubenfonseca and @stephenbawks
This patch release primarily address a regression for custom builds that remove METADATA directory from installations, e.g., Serverless Framework with
This patch release primarily address a regression for custom builds that remove METADATA directory from installations, e.g., Serverless Framework with python-requirements plugin.
We have switched to bumping versions statically as of this release - SAM, CDK, Console, and Layer customers weren't affected.
Huge thanks to @bronzeson for reporting it, and @CJTurpie for reproducing it with Serverless framework plugin.
@dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa and @leandrodamascena
We packed this release with a bunch of new features and performance improvements:
We packed this release with a bunch of new features and performance improvements:
CodePipelineJobEvent event source⭐ Huge thanks to new contributors: @roger-zhangg and @darnley!!
Docs: Multiple CORS origins
We added support for multiple origins in CORS when defining an event handler. Supporting multiple CORS origins enables API calls from different domains and the integration of various sources. Your existing code will continue to work as it is.
SQS event notifications can sometimes be ingested into Lambda via an intermediary such as Kinesis Firehose (i.e. Lambda event source), for various architectural reasons - batching, retries, etc. However, from the Lambda function's perspective, the intermediary might not be too important; what's important is the SQS event notification itself. Now you can easily parse and access the inner payload for Kinesis Firehose-wrapped SQS events.
CodePipelineJobEvent event sourceThanks to @darnley, we found out that using the CodePipelineJobEvent came with a performance penalty, and we fixed it by optimizing the way we load dependencies.
We've completely revamped and fine-tuned all the samples and snippets for our Feature Flags and Batch Processing utilities! We took the time to bring the examples closer to real-world usage and fixed any syntax errors. We can't wait for you to try them out!
@darnley, @dependabot, @dependabot[bot], @github-actions, @github-actions[bot], @heitorlessa, @leandrodamascena, @roger-zhangg, @rubenfonseca, @sthulb and Release bot
Nothing published for this version
This release is packed with a number of improvements:
This release is packed with a number of improvements:
And… a ton of documentation improvements.
⭐ Huge thanks to new contributors: @theipster (S3 events), @neilramsay (Data Class debug), @arjanschaaf (Batch docs) and @leif-ye (API Gateway Event Source)
Docs: Observability providers
You can now send logs to the observability provider of your choice via Lambda Extensions. In most cases, you shouldn't need any custom Logger configuration, and logs will be shipped asynchronously with no performance impact.
Docs: Built-in envelopes, Parser
S3 event notifications can be sometimes be ingested into Lambda via an intermediary such as an SQS queue (i.e. Lambda event source), for various architectural reasons - batching, retries, etc. However, from the Lambda function's perspective, the intermediary might not be too important; what's important is the S3 event notification itself. Now you can easily parse and access the inner payload for SQS-wrapper S3 events.
Docs: Debugging
You can now print out the fields of a data class instance to obtain more information. All classes come with a __str__ method that generates a dictionary string which can be quite useful for debugging. Sensitive fields such as secret_access_key and session_token, are labeled as [SENSITIVE], to prevent any accidental disclosure of confidential information.
You can now manually flush the metrics at any time. This is useful when not running within a standard Lambda handler (e.g: Lambda Web Adapter), where the @log_metrics decorator does not work as intended.
@arjanschaaf, @dependabot, @dependabot[bot], @heitorlessa, @leandrodamascena, @leif-ye, @neilramsay, @rubenfonseca, @theipster and Release bot
This patch release addresses a regression in Batch for anyone not using Pydantic or installing Powertools via Layers.
This patch release addresses a regression in Batch for anyone not using Pydantic or installing Powertools via Layers.
Huge thanks to @walmsles ⭐ for spotting it and sending a fix in record time.
@dependabot, @dependabot[bot], @heitorlessa, @leandrodamascena, @rubenfonseca, @walmsles and Release bot
> Duplicate: due to a GitHub glitch this notification might have appeared earlier.
Duplicate: due to a GitHub glitch this notification might have appeared earlier.
This release adds support for 3.10.
@dependabot, @dependabot[bot], @heitorlessa, @rubenfonseca and Release bot
This release improves the developer experience using the Parameters utility, fixes a bug on the CodePipeline event source and adds several documentati
This release improves the developer experience using the Parameters utility, fixes a bug on the CodePipeline event source and adds several documentation improvements!
⭐ Huge thanks to our new contributor @neilramsay
Docs: Cache TTL, SSMProvider
You can now set the POWERTOOLS_PARAMETERS_MAX_AGE and POWERTOOLS_PARAMETERS_SSM_DECRYPT environment variables to set defaults values for all parameters fetched by this utility. This avoids having to pass max_age and decrypt when you fetch several parameters.
@dependabot, @dependabot[bot], @djfurman, @leandrodamascena, @neilramsay, @rubenfonseca and Release bot
This release improves the authoring experience for Batch processing (-boilerplate), fix a bug between Batch and Pydantic integration for poison pills,
This release improves the authoring experience for Batch processing (-boilerplate), fix a bug between Batch and Pydantic integration for poison pills, and several documentation and static typing improvements!
⭐ Huge thanks to new contributors: @michael-k (docs) and @LuckIlNe (Batch pydantic bugfix)
Docs: Amazon SQS, Amazon Kinesis Data Streams, Amazon DynamoDB Streams
Batch feature is generally used for building more resilient data pipelines ranging from ETL to Change Data Capture to AWS automation.
This release significantly removes boilerplate and makes it less error prone to author batch processors. You can now use process_partial_response and async_process_partial_response within your Lambda handler to kick off processing, handle failures and return the expected response for partial failures in Lambda.
Before
After
Pydantic provides parsing and deep data validation mechanisms. It's commonly used with Batch feature to author and validate data models.
Thanks to @LuckIlNe, we now correctly handle malformed messages that fail validation early (poison pills), thus not breaking the partial failure mechanism. Previously, any record that doesn't conform with an early model validation would not fail gracefully.
Docs: Idempotency new diagrams, terminology, and Idempotency record expiration vs DynamoDB time-to-live (TTL).
Thanks to a discussion with @pmarko1711, we revamped the Idempotency documentation to include more sequence diagrams to visually explain the different idempotent scenarios. We also clarified terminologies like Idempotency Record, and a confusion between Idempotency Record Expiration and DynamoDB TTL.
The latter can be used as a fine-grained concurrency mechanism.
<img width="1529" alt="image" src="https://user-images.githubusercontent.com/3340292/230626106-bd1b98bf-cabb-4471-8417-9657c6fb19b4.png">
Pydantic integration examples now use the new Json model from Pydantic to auto-deserialize JSON strings into Pydantic models. This removes excessive boilerplate when working with SQS and Kinesis Data Streams in Batch.
All examples now recommend use of process_partial_response over the legacy decorator, including a new question in the FAQ section to clarify them.
When using Mypy for applications using Pydantic models provided by Parser, you couldn't use nested models for SQS, Kinesis, and DynamoDB Streams.
This quality of life improvement also allows you to use higher-level models like Json to auto-deserialize JSON strings in common Lambda Event Source fields like SQS.body.
from aws_lambda_powertools.utilities.parser import BaseModel, validator
from aws_lambda_powertools.utilities.parser.models import (
DynamoDBStreamChangedRecordModel,
DynamoDBStreamRecordModel,
KinesisDataStreamRecord,
KinesisDataStreamRecordPayload,
SqsRecordModel,
)
from aws_lambda_powertools.utilities.parser.types import Json, Literal
class Order(BaseModel):
item: dict
# SQS example
class OrderSqs(SqsRecordModel):
body: Json[Order]
# Kinesis example
class OrderKinesisPayloadRecord(KinesisDataStreamRecordPayload):
data: Json[Order]
class OrderKinesisRecord(KinesisDataStreamRecord):
kinesis: OrderKinesisPayloadRecord
# DynamoDB Streams example
class OrderDynamoDBChangeRecord(DynamoDBStreamChangedRecordModel):
NewImage: Optional[OrderDynamoDB]
OldImage: Optional[OrderDynamoDB]
class OrderDynamoDBRecord(DynamoDBStreamRecordModel):
dynamodb: OrderDynamoDBChangeRecord
@LuckIlNe, @dependabot, @dependabot[bot], @heitorlessa, @leandrodamascena, @michael-k and Release bot
This release adds support for S3 Event Notifications via EventBridge in Event Source Data Classes, and a bug fix for Feature Flags to handle falsy con
This release adds support for S3 Event Notifications via EventBridge in Event Source Data Classes, and a bug fix for Feature Flags to handle falsy context values correctly.
⭐ Huge welcome to new contributors: @ajwad-shaikh and @ivica-k
A new use case is to process S3 Events with the newer and faster EventBridge integration. Previously, EventBridge integration with S3 would use CloudTrail leading up to a few minutes delays.
With the new integration, there is a slightly new payload that we had to support in order to ease that integration.
Thanks to @ivica-k, you can now use S3EventBridgeNotificationEvent!
from aws_lambda_powertools.utilities.data_classes import S3EventBridgeNotificationEvent, event_source
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=S3EventBridgeNotificationEvent)
def lambda_handler(event: S3EventBridgeNotificationEvent, context: LambdaContext):
bucket_name = event.detail.bucket.name
file_key = event.detail.object.key
new_storage_class = event.detail.destination_storage_class
...
Thanks to @ajwad-shaikh for reporting and fixing this bug (incl. @ran-isenberg), you can now handle flag variants when their context values are falsy, e.g., empty lists, empty strings, False, 0, etc.
Example that wasn't possible before this release
Flag
{
"sales_offer": {
"default": false,
"rules": {
"unpaid_users": {
"when_match": true,
"conditions": [ {"action": "EQUALS", "key": "is_paid", "value": 0} ]
}
}
}
Context
{
"is_paid": 0,
}
@ajwad-shaikh, @dependabot, @dependabot[bot], @heitorlessa, @ivica-k, @ran-isenberg and Release bot
This release brings support for parsing S3 Event Notifications via EventBridge and support for custom properties on the ActiveMQ event source data cla
This release brings support for parsing S3 Event Notifications via EventBridge and support for custom properties on the ActiveMQ event source data class.
⭐️ Huge thanks for our first-time contributors @alexaiss and @ivica-k, and also @tibbe for the typing hot-fix!
Amazon S3 can send event notifications with Amazon EventBridge. We added support for parsing those events in Lambda using the new S3EventNotificationEventBridgeModel.
Thank you @robert-malai for capturing this feature gap!
When integrating with Active MQ, Lambda supports JMS custom properties. After this change, you can also access them when using the ActiveMQ event source data class.
@alexaiss, @dependabot, @dependabot[bot], @heitorlessa, @ivica-k, @rubenfonseca, @sthulb, @tibbe and Release bot
chore(ci): replace deprecated set-output commands (#1957) by @cibinmathew
This patch release reverts a regression in Idempotency when using static_pk_value for custom composite keys in DynamoDB Persistence Layer - huge thanks to @Tankanow for reporting and fixing it.
⭐ Big thanks to new contributors: @KeltonKarboviak on inconsistencies on Parameters docs (#1966), and @cibinmathew on upgrading GitHub Actions set-output command in our workflows.
@KeltonKarboviak, @cibinmathew, @Tankanow, @dependabot, @dependabot[bot], @heitorlessa and Release bot
This release contains a new feature on Batch Processing, along with enhancements and bug fixes to Logger and Feature Flags utilities.
This release contains a new feature on Batch Processing, along with enhancements and bug fixes to Logger and Feature Flags utilities.
⭐ Huge welcome to the new contributors: @royygael, @iago1460
You can now use SQS FIFO queues with the Batch Processing utility. We stop processing messages after the first failure and return all failed and unprocessed messages natively. This helps preserve the ordering of messages in your queue.
⭐ Thanks to @whoDoneItAgain for reporting this feature gap.
We now allow exception and exception_name attributes as extra fields in all logging levels. Previously, we dropped those attributes in non-error logging levels (e.g: INFO).
⭐ Thanks to @iago1460 for reporting this bug and submitting the fix!
Finally, we have two new community posts on Feature Flags from @ran-isenberg:
@dependabot, @dependabot[bot], @heitorlessa, @iago1460, @leandrodamascena, @royygael, @rubenfonseca and Release bot
This release is packed with new features and enhancements, specifically to Batch Processing, Metrics and Idempotency utility.
This release is packed with new features and enhancements, specifically to Batch Processing, Metrics and Idempotency utility.
⭐ Huge welcome to new contributors: @BakasuraRCE, @prudnikov, @kavichu, @marcraminv
Thanks to @BakasuraRCE, we’re adding a new specialized processor for high concurrency jobs that can process thousands of messages sub-second (thanks to @sthulb for load testing) - AsyncBatchProcessor and async_batch_processor.
These will use Python’s asyncio.gather to call your record handler with all records at the same time. During load testing, we’ve managed to process 5500 messages in approximately 300ms compared to 1.2 seconds with BatchProcessor synchronous counterpart.
You can now create high-resolution (1s) metrics that are common for use cases like IoT, telemetry, time-series, real-time incident, etc. Previously, metrics were only created with 60-second resolution. This is an opt-in feature.
Thanks to @prudnikov, you can now optionally set default dimensions for single metrics. These are individual application or operational metrics that despite being isolated from a larger set of metrics, they do share the same set of dimensions (avoid repetition, sparse metrics).
Thanks to @mploski, any Python function decorated with idempotent_function can now safely be called from threads. Previously, we used to create higher-level AWS SDK clients which didn’t support threading - calling functions decorated back then could result in unforeseen side-effects.
Example
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import current_thread
from aws_lambda_powertools.utilities.idempotency import (
DynamoDBPersistenceLayer,
idempotent_function,
)
TABLE_NAME = os.getenv("IdempotencyTable", "")
persistence_layer = DynamoDBPersistenceLayer(table_name=TABLE_NAME)
threads_count = 2
@idempotent_function(persistence_store=persistence_layer, data_keyword_argument="record")
def record_handler(record):
time_now = time.time()
return {"thread_name": current_thread().name, "time": str(time_now)}
def lambda_handler(event, context):
with ThreadPoolExecutor(max_workers=threads_count) as executor:
futures = [executor.submit(record_handler, **{"record": event}) for _ in range(threads_count)]
return [
{"state": future._state, "exception": future.exception(), "output": future.result()}
for future in as_completed(futures)
]
@BakasuraRCE, @dependabot, @dependabot[bot], @heitorlessa, @kavichu, @leandrodamascena, @marcraminv, @mploski, @prudnikov and Release bot
Your coding agent can read these notes before it upgrades. Set up the MCP server →