Releases: aws-powertools/powertools-lambda-typescript
v2.28.1
Summary
This patch release addresses an issue in the Commons package utility introduced in v2.28.0 that caused a runtime error.
This issue affects only those who have lambda code that depends directly or indirectly on the getXrayTraceDataFromEnv function in the Commons package and who are bundling that lambda with ESBuild to an ES module.
We recommend updating to the latest version to avoid the issue.
Changes
📜 Documentation updates
- chore(ci): bumped the layer verison from 39 to 40 (#4683) by @svozza
- chore(deps): bump @types/node from 24.8.1 to 24.9.1 (#4673) by @dependabot[bot]
- chore(ci): bumped the layer verison from 38 to 39 (#4671) by @sdangol
🔧 Maintenance
- fix(logger): fix esbuild ESM bundler error (#4678) by @svozza
- chore(deps): bump @types/node from 24.8.1 to 24.9.1 (#4673) by @dependabot[bot]
- chore(deps-dev): bump lint-staged from 16.2.4 to 16.2.5 (#4672) by @dependabot[bot]
This release was made possible by the following contributors:
@dependabot[bot], @github-actions[bot], @sdangol, @svozza, dependabot[bot] and github-actions[bot]
v2.28.0
Summary
We are excited to announce that the REST API Event Handler now supports catch-all routes, allowing you to use regex patterns directly when defining route paths. We've also added the ability to split routers using includeRouter for both REST API and AppSync GraphQL Event Handlers.
We’ve also reverted the SQSRecordSchema change that caused failed parsing of records when md5OfMessageAttributes was null.
📜 Announcement: You can now find our documentation on the official AWS documentation domain at https://docs.aws.amazon.com/powertools/typescript/latest/
⭐ Congratulations @mdesousa, @thiagomeireless, @alex-karo for their first PR merged in the project 🎉
Catch-all route
You can now use regex patterns in your routes to handle arbitrary or deeply nested paths.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
const app = new Router();
// Instead of defining every possible path
app.get('/files/:folder/:subfolder/:filename');
// Use regex to handle any depth
app.get(/\/files\/.*/, async (reqCtx) => {
// This will match:
// /files/docs/2025/report.pdf
// /files/images/avatars/user1/profile.jpg
// /files/any/number/of/nested/paths/file.txt
});We recommend having explicit routes whenever possible. Catch-all routes should be used sparingly and the pattern should be documented.
Split Routers
You can now define routes in separate files and import them into a main router file, improving code organization and maintainability.
REST API Event Handler
// userRoutes.ts
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
const userRouter = new Router();
userRouter.get('/', listUsers);
userRouter.post('/', createUser)
userRouter.get('/:id', getUser)
export { userRouter };// orderRoutes.ts
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
const orderRouter = new Router();
orderRouter.get('/orders', listOrders);
orderRouter.post('/orders', createOrder);
orderRouter.put('/orders/:id/status', updateStatus);
export { orderRouter };// main.ts
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { APIGatewayProxyEvent } from 'aws-lambda';
import type { Context } from 'aws-lambda';
import { userRouter } from './userRoutes.js';
import { orderRouter } from './orderRoutes.js';
const app = new Router();
// Split Routers
app.includeRouter(userRouter, { prefix: '/users' });
app.includeRouter(orderRouter, { prefix: '/orders' });
export const handler = async (event: APIGatewayProxyEvent, context: Context) =>
app.resolve(event, context);AppSync GraphQL Event Handler
// postRouter.ts
import { Router } from '@aws-lambda-powertools/event-handler/appsync-graphql';
const postRouter = new Router();
postRouter.onQuery('getPosts', getPosts);
postRouter.onMutation('createPost', createPost);
export { postRouter };//userRouter.ts
import { Router } from '@aws-lambda-powertools/event-handler/appsync-graphql';
const userRouter = new Router();
userRouter.onQuery('getUsers', getUsers);
export { userRouter };// main.ts
import { AppSyncGraphQLResolver } from '@aws-lambda-powertools/event-handler/appsync-graphql';
import type { Context } from 'aws-lambda';
import { postRouter } from './postRouter';
import { userRouter } from './userRouter';
const app = new AppSyncGraphQLResolver();
app.includeRouter([postRouter, userRouter]);
export const handler = async (event: unknown, context: Context) =>
app.resolve(event, context);Changes
- improv(event-handler): ended response stream when body is null (#4651) by @sdangol
- fix(idempotency): add null check for idempotencyHandler before calling handleMiddyOnError (#4643) by @mdesousa
- fix(parser): updated the SQSRecordSchema to make the md5OfMessageAttributes nullable (#4632) by @sdangol
- fix(event-handler): allow http handlers to return duplex streams (#4629) by @svozza
- fix(logger): correct persistentLogAttributes warning behavior (#4627) by @alex-karo
- feat(event-handler): added support for catch all route (#4582) by @sdangol
- improv(event-handler): rename ServiceError class to HttpError (#4610) by @svozza
- docs(parser): correct typos in example code for middleware (#4607) by @thiagomeireless
- test: update domain in e2e tests (#4606) by @dreamorosi
- ci: add
--deleteflag to docs publish command (#4584) by @dreamorosi - feat(event-handler): added
includeRoutermethod to split routes (#4573) by @sdangol - chore: sanitize CI inputs via env var (#4528) by @dreamorosi
- feat(event-handler): Add
includeRoutersupport to AppSync GraphQL resolver (#4457) by @arnabrahman
📜 Documentation updates
- chore(ci): bumped the layer verison from 38 to 39 (#4671) by @sdangol
- chore(deps): bump aws-cdk-lib from 2.219.0 to 2.220.0 in the aws-cdk group across 1 directory (#4665) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 88 updates (#4664) by @dependabot[bot]
- chore(deps): bump @types/node from 24.8.0 to 24.8.1 (#4661) by @dependabot[bot]
- chore(deps): bump @types/node from 24.7.2 to 24.8.0 (#4654) by @dependabot[bot]
- chore(deps): bump @types/aws-lambda from 8.10.155 to 8.10.156 (#4653) by @dependabot[bot]
- chore(deps): bump esbuild from 0.25.10 to 0.25.11 (#4648) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.21 to 9.6.22 in /docs (#4647) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
00f9276tof5c556ain /docs (#4646) by @dependabot[bot] - chore(deps): bump the aws-sdk-v3 group across 1 directory with 49 updates (#4637) by @dependabot[bot]
- chore(deps): bump @types/node from 24.7.1 to 24.7.2 (#4642) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 2 updates (#4638) by @dependabot[bot]
- chore(deps): bump @types/node from 24.7.0 to 24.7.1 (#4628) by @dependabot[bot]
- chore(deps): bump @types/aws-lambda from 8.10.153 to 8.10.155 (#4617) by @dependabot[bot]
- chore: add AWS bootstrap js + update urls (#4614) by @dreamorosi
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 99 updates (#4619) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.3.2 to 0.4.0 in /docs (#4615) by @dependabot[bot]
- chore(deps): bump @types/node from 24.6.2 to 24.7.0 (#4618) by @dependabot[bot]
- chore(deps): bump @types/node from 24.6.1 to 24.6.2 (#4613) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4589) by @dependabot[bot]
- chore(deps): bump typescript from 5.9.2 to 5.9.3 in the typescript group across 1 directory (#4599) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
86d21dato00f9276in /docs (#4598) by @dependabot[bot] - chore(deps): bump @types/aws-lambda from 8.10.152 to 8.10.153 (#4600) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.20 to 9.6.21 in /docs (#4596) by @dependabot[bot]
- chore(deps): bump @types/node from 24.6.0 to 24.6.1 (#4601) by @dependabot[bot]
- chore(deps): bump @types/node from 24.5.2 to 24.6.0 (#4595) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 45 updates (#4592) by @dependabot[bot]
- docs: update install command for parser (#4585) by @dreamorosi
- chore(deps): bump tsx from 4.20.5 to 4.20.6 (#4580) by @dependabot[bot]
- ci: improve linting checks (#4545) by @dreamorosi
- chore(ci): update layer ARN on documentation (#4535) by @sdangol
🔧 Maintenance
- chore(deps-dev): bump lint-staged from 16.2.4 to 16.2.5 (#4672) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.219.0 to 2.220.0 in the aws-cdk group across 1 directory (#4665) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 4.30.8 to 4.30.9 (#4666) by @dependabot[bot]
- feat(metrics): use async local storage for metrics (#4663) by @svozza
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 88 updates (#4664) by @dependabot[bot]
- chore(deps): bump @types/node from 24.8.0 to 24.8.1 (#4661) by @dependabot[bot]
- chore: update CONTRIBUTING.md (#4659) by @ConnorKirk
- improv(commons): Make X-Ray trace ID access more robust (#4658) by @svozza
- chore(deps): bump @types/node from 24.7.2 to 24.8.0 (#4654) by @dependabot[bot]
- chore(deps): bump aws-xray-sdk-core from 3.10.3 to 3.11.0 (#4656) by @[dependabot[bot]](https://github.com...
v2.27.0
Summary
We're excited to announce an update to our Event Handler utility, featuring new middleware for CORS (Cross-Origin Resource Sharing) configuration and automatic response compression. We have also added support for Route Prefixes which allows you to avoid repeating a shared prefix in each route definition.
We've listened to your feedback and also made some slight changes to the type signature in the handlers to improve developer experience.
We have also made the error handlers more versatile by allowing a Response object or a JavaScript object to be returned from the error handler.
⭐ Congratulations @guillemcomerma for their first PR merged in the project, and thank you to @shrivarshapoojari and @dani-abib for their contributions 🎉
CORS Middleware
The CORS middleware ensures CORS headers are returned as part of the response when your functions match the path invoked and the Origin matches one of the allowed values.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import { cors } from '@aws-lambda-powertools/event-handler/experimental-rest/middleware';
import type { Context } from 'aws-lambda';
const app = new Router();
app.use(
cors({
origin: 'https://example.com',
maxAge: 300,
})
);
app.get('/todos/:todoId', async ({ params: { todoId } }) => {
const todo = await getTodoById(todoId);
return { todo };
});
export const handler = async (event: unknown, context: Context) =>
app.resolve(event, context);
/**
When invoked from a valid origin, this returns:
{
"statusCode": 200,
"headers": {
"access-control-allow-credentials": "false",
"access-control-allow-origin": "https://example.com",
"content-type": "application/json"
},
"multiValueHeaders": {
"access-control-allow-headers": [
"Authorization",
"Content-Type",
"X-Amz-Date",
"X-Api-Key",
"X-Amz-Security-Token"
],
"access-control-allow-methods": [
"DELETE",
"GET",
"HEAD",
"PATCH",
"POST",
"PUT"
]
},
"body": "{\"todoId\":\"123\",\"task\":\"Example task\",\"completed\":false}",
"isBase64Encoded": false
}
**/Compress Middleware
The compress middleware automatically compresses responses using gzip and base64 encodes them when the client indicates support via the Accept-Encoding header.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import { compress } from '@aws-lambda-powertools/event-handler/experimental-rest/middleware';
import type { Context } from 'aws-lambda';
const app = new Router();
app.use(compress());
app.get('/todos/:todoId', async ({ params: { todoId } }) => {
const todo = await getTodoById(todoId);
return { todo };
});
export const handler = async (event: unknown, context: Context) =>
app.resolve(event, context);
/**
When invoked with the following request,
{
"headers": {
"Accept-Encoding": "gzip"
},
"resource": "/todos/1",
"path": "/todos/1",
"httpMethod": "GET"
}
it would return,
{
"statusCode": 200,
"multiValueHeaders": {
"Content-Type": [
"application/json"
],
"Content-Encoding": [
"gzip"
]
},
"body": "H4sIAAAAAAACE42STU4DMQyFrxJl3QXln96AMyAW7sSDLCVxiJ0Kqerd8TCCUOgii1EmP/783pOPXjmw+N3L0TfB+hz8brvxtC5KGtHvfMCIkzZx0HT5MPmNnziViIr2dIYoeNr8Q1x3xHsjcVadIbkZJoq2RXU8zzQROLseQ9505NzeCNQdMJNBE+UmY4zbzjAJhWtlZ57sB84BWtul+rteH2HPlVgWARwjqXkxpklK5gmEHAQqJBMtFsGVygcKmNVRjG0wxvuzGF2L0dpVUOKMC3bfJNjJgWMrCuZk7cUp02AiD72D6WKHHwUDKbiJs6AZ0VZXKOUx4uNvzdxT+E4mLcMA+6G8nzrLQkaxkNEVrFKW2VGbJCoCY7q2V3+tiv5kGThyxfTecDWbgGz/NfYXhL6ePgF9PnFdPgMAAA==",
"isBase64Encoded": true
}
**/Route Prefixes
When defining multiple routes related to a specific resource, you can use the prefix constructor parameter when creating a new Router instance, and we'll automatically strip it from the request path before matching routes. This will prevent you to avoid repeating the prefix in each route definition.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Context } from 'aws-lambda';
const app = new Router({ prefix: '/todos' });
// matches POST /todos
app.post('/', async ({ req: { headers } }) => {
const todos = await getUserTodos(headers.get('Authorization'));
return { todos };
});
export const handler = async (event: unknown, context: Context) =>
app.resolve(event, context);Type Signature Changes
We’ve also made changes to some type signatures to reduce parameter complexity.
The path parameters in the route handlers have been moved to reqCtx
app.get('/todos/:todoId', async (reqCtx) => {
return { id: reqCtx.params.todoId };
});
Previously middleware used positional arguments:
const middleware: Middleware = async (params, reqCtx, next) => {
logger.info('Request processed');
await next();
};Now, we have changed it to be an object so customers can pick only the parameters that they want and also moved the params parameter to reqCtx
const middleware: Middleware = async ({ reqCtx: { params }, next }) => {
logger.info('Request processed');
await next();
};We have also changed the request property to req in the RequestContext type to maintain consistency with the res property.
Improvements on Error Handling
Error handlers can now return a Response object or a JavaScript object that will be auto-serialized.
import {
HttpStatusCodes,
Router,
} from '@aws-lambda-powertools/event-handler/experimental-rest';
import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda/handler';
const logger = new Logger();
const app = new Router({ logger });
app.errorHandler(GetTodoError, async (error, reqCtx) => {
logger.error('Unable to get todo', { error });
return {
statusCode: HttpStatusCodes.BAD_REQUEST,
message: `Bad request: ${error.message} - ${reqCtx.req.headers.get('x-correlation-id')}`,
};
});
app.get('/todos/:todoId', async ({ params: { todoId } }) => {
const todo = await getTodoById(todoId); // May throw GetTodoError
return { todo };
});
export const handler = async (event: unknown, context: Context) =>
app.resolve(event, context);Changes
- chore: sanitize CI inputs via env var (#4528) by @dreamorosi
- improv(event-handler): rename HttpErrorCodes to HttpStatusCodes (#4543) by @dreamorosi
- docs(idempotency): fix dataKeywordArgument reference and remove unused test code (#4537) by @guillemcomerma
- improv(event-handler): made error handler responses versatile (#4536) by @sdangol
- chore(ci): add
registry-urltosetup-nodesteps to fix Scorecard packaging check (#4539) by @shrivarshapoojari - improv(event-handler): changed path parameter in middleware and routehandler signature (#4532) by @sdangol
- improv(event-handler): changed the Middleware and RequestContext signatures (#4530) by @sdangol
- fix(event-handler): fixed CORS behaviour not aligned with CORS spec (#4512) by @sdangol
- feat(event-handler): implemented route prefixes in HTTP event handler (#4523) by @sdangol
- feat(event-handler): throw error when middleware does not await next() (#4511) by @svozza
- chore: always append
PTEnvto UA string (#4522) by @dreamorosi - fix(event-handler): run global middleware on all requests for REST API (#4507) by @svozza
- fix(batch): fixed the build issue with Batch processor due to missing dependencies (#4498) by @sdangol
- feat(event-handler): added compress middleware for the REST API event handler (#4495) by @sdangol
- feat(event-handler): add CORS middleware support (#4477) by @dcabib
📜 Documentation updates
- chore(ci): update layer ARN on documentation (#4535) by @sdangol
- docs(event-handler): update to new APIs before release (#4542) by @dreamorosi
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4527) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 62 updates (#4526) by @dependabot[bot]
- docs(event-handler): general improvements (#4517) by @dreamorosi
- chore(deps): bump esbuild from 0.25.9 to 0.25.10 (#4503) by @dependabot[bot]
- chore(deps): bump @types/node from 24.5.1 to 24.5.2 (#4505) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.3.1 to 0.3.2 in /docs (#4508) by @dependabot[bot]
- chore(deps): bump @types/node from 24.5.0 to 24.5.1 (#4501) by @dependabot[bot]
- fix(batch): fixed the build issue with Batch processor due to missing dependencies (#4498) by @sdangol
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 88 updates (#4494) by @dependabot[bot]
- chore(deps): bump @types/node from 24.4.0 to 24.5.0 (#4497) by @dependabot[bot]
- chore(deps): bump @types/node from 24.3.1 to 24.4.0 (#4493) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.19 to 9.6.20 in /docs (#4492) by @[...
v2.26.1
Summary
This patch release addresses a regression with the Batch Processing utility introduced in v2.26.0 that caused a bundling error due to an internal dependency not being declared in the package.json.
This bug affects only those who are using Batch Processing without other Powertools for AWS utilities and who have already upgraded to v2.26.0 which was released on 12/09/2025.
We recommend updating to the latest version to avoid the issue.
⭐ Congratulations to @Grmiade for identifying this issue and fixing it with their first PR merged in the project 🎉
Changes
📜 Documentation updates
- chore(ci): update layer ARN on documentation (#4488) by @sdangol
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4443) by @dependabot[bot]
- docs(batch): added documentation for the parser integration feature in batch processor (#4435) by @sdangol
🔧 Maintenance
- fix(batch): declare the @aws-lambda-powertools/commons dependency (#4484) by @Grmiade
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4443) by @dependabot[bot]
- chore(deps-dev): bump zod from 4.1.7 to 4.1.8 (#4473) by @dependabot[bot]
- chore(deps): bump actions/github-script from 7.0.1 to 8.0.0 (#4432) by @dependabot[bot]
This release was made possible by the following contributors:
@Grmiade, @dependabot[bot], @github-actions[bot], @sdangol, dependabot[bot] and github-actions[bot]
v2.26.0
Summary
We're excited to announce support for API Gateway REST APIs in the Event Handler utility. This simplifies routing and processing of events in AWS Lambda functions by allowing you to define specific handlers that corresponds to routes in your REST APIs with minimal boilerplate code.
We have also integrated the Parser utility with Batch Processing, enabling automatic validation of payloads from SQS, Kinesis and DynamoDB streams.
Furthermore, we have added support for custom error handlers to the AppSync GraphQL event handler resolver, with automatic marshalling of errors to the expected AppSync format and logging built-in.
⭐ Congratulations @dcabib for their first PR merged in the project and to @arnabrahman for their continued contributions to AppSync event handler 🎉
Working with API Gateway REST APIs
Key Features
- Lightweight routing to reduce boilerplate code for API Gateway REST APIs
- Built-in middleware engine for executing custom logic when processing requests and responses
- Supports micro function (one or a few routes) and monolithic functions (all routes)
To get started install the Event Handler utility by running:
npm install @aws-lambda-powertools/event-handler
Registering a route
You can register routes to match HTTP verbs and specific paths. Each HTTP verb corresponds to a method on the REST handler Router class and the path is the first argument of that method
When a request is received, the event handler will automatically convert the event into a Request object and give you access to the current request context, including this request object, the raw event, a Response object, and the lambda context.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Context, APIGatewayProxyEvent } from 'aws-lambda';
const app = new Router();
app.get('/ping', async (_, {request: Request, res: Response, context: Context, event: APIGatewayProxyEvent}) => {
return { message: 'pong' };
});
export const handler = async (event: unknown, context: Context) => {
return app.resolve(event, context);
};We also support dynamic routes in the format path/:identifer, where the :identifier will be extracted as a named parameter and passed to your route handler.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Context } from 'aws-lambda/handler';
const logger = new Logger({});
const app = new Router({ logger });
app.get('/todos/:todoId', async ({ todoId }) => {
const todo = await getTodoById(todoId);
return { todo };
});
export const handler = async (event: unknown, context: Context) => {
return app.resolve(event, context);
};Autoserialization
For your convenience, when you return a JavaScript object from your route handler, we automatically return an appropriate API Gateway response object by doing the following:
- Auto-serialize the response to JSON and trim whitespace
- Include the response under the appropriate equivalent of a body
- Set the Content-Type header to application/json
- Set the HTTP status code to 200 (OK)
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Context } from 'aws-lambda/handler';
const logger = new Logger({});
const app = new Router({ logger });
app.get('/todos/:todoId', async ({ todoId }) => {
const todo = await getTodoById(todoId);
return { todo };
});
export const handler = async (event: unknown, context: Context) => {
return app.resolve(event, context);
};
/**
This returns:
{
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: '{"todo\":"an-id"}',
isBase64Encoded": false
}
**/Error Handling
You can use errorHandler function to gracefully handle exceptions. This works by passing an error constructor and an error handler function to the error registration method,
Event handler comes with a number of error classes such as BadRequest, InternalServerError and so on. Using these will ensure the correct HTTP code is returned. You can also extend the base error class to create your custom errors.
import { Router, BadRequestError } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Context } from 'aws-lambda/handler';
const logger = new Logger({});
const app = new Router({ logger });
app.errorHandler(BadRequestError, async (error: BadRequestError) => {
return {
error: 'Validation Error',
message: `Error: ${error.message}`,
}
});
app.get('/todos/:todoId', async ({ todoId }) => {
if(todoId == null) throw BadRequestError('todoId cannot be null');
const todo = await getTodoById(todoId);
return { todo };
});
export const handler = async (event: unknown, context: Context) => {
return app.resolve(event, context);
};
/**
This returns:
{
statusCode: 400,
headers: {
'Content-Type': 'application/json'
},
body: '{"error":"Validation Error","message":"Error: todoId cannot be null"}'
isBase64Encoded": false
}
**/Note that unhandled errors will be caught in the Router and converted to an HTTP 500 error response.
Decorators
You can also use decorators for registering route and error handlers.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda/handler';
const logger = new Logger({});
const app = new Router({ logger });
class Lambda {
@app.errorHandler(BadRequestError)
public async handleBadRequest(error: BadRequestError) {
return {
error: 'Validation Error',
message: `Error: ${error.message}`,
};
}
@app.get('/todos/:todoId')
public async getTodos({ todoId }: { todoId: string }) {
const todo = await getTodoById(todoId);
return { todo };
}
public async handler(event: unknown, context: Context) {
return app.resolve(event, context, { scope: this });
}
}
const lambda = new Lambda();
export const handler = lambda.handler.bind(lambda);Middleware
Use middleware when you need to run custom logic before or after your route handler executes. Every middleware is simply a function that receives the following arguments:
- params Route parameters extracted from the URL path
- reqCtx Request context containing the event, Lambda context, request, and response objects
- next A function to pass control to the next middleware in the chain
Middleware can be applied on specific routes, globally on all routes, or a combination of both.
Middleware execution follows an onion pattern where global middleware runs first in pre-processing, then route-specific middleware. After the handler executes, the order reverses for post-processing.
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import type { Middleware } from '@aws-lambda-powertools/event-handler/types';
import type { Context } from 'aws-lambda';
const app = new Router();
// Global middleware - executes first in pre-processing, last in post-processing
app.use(async (params, reqCtx, next) => {
reqCtx.res.headers.set('x-pre-processed-by', 'global-middleware');
await next();
reqCtx.res.headers.set('x-post-processed-by', 'global-middleware');
});
// Route-specific middleware - executes second in pre-processing, first in post-processing
const routeMiddleware: Middleware = async (params, reqCtx, next) => {
// ...
};
app.get('/todos', async () => {
const todos = await getAllTodos();
return { todos };
});
// route specific middleware
app.post('/todos', [routeMiddleware], async (params, reqCtx) => {
// ...
});
export const handler = async (event: unknown, context: Context) => {
return app.resolve(event, context);
};Parser Integration with Batch Processing
The Batch Processing utility now supports integration with the Parser utility, enabling automatic validation and transformation of batch records before processing. You can use built in transformers: json , base64 , and unmarshall to transform your schemas into common data formats. It is compatible with SQS, Kinesis Data Streams and DynamDB Streams. You can either use a complete schema or even just an inner schema for the parsing.
Example
import {
BatchProcessor,
EventType,
processPartialResponse,
} from '@aws-lambda-powertools/batch';
import { parser } from '@aws-lambda-powertools/batch/parser';
import type { SQSHandler, SQSRecord } from 'aws-lambda';
import { z } from 'zod';
const customSchema = z.object({
name: z.string(),
age: z.number(),
});
const processor = new BatchProcessor(EventType.SQS, {
parser,
innerSchema: customSchema,
transformer: 'json',
});
const recordHandler = async ({
body: { name, age },
}: SQSRecord & { body: z.infer<typeof customSchema> }) => {
// this is safe to use because it's parsed
};
export const handler: SQSHandler = async (event, context) =>
processPartialResponse(event, recordHandler, processor, {
context,
});Error Handling with AppSync GraphQL
We've also added error handling capabilities to the AppSync GraphQL resolver. You can register your custom error handlers for specific error classes using app.exceptionHandler(ErrorClass, handler) . All errors are automatically formatted for AppSync compatibility and include logging for better observability, making it easier to build GraphQL APIs with proper error ...
v2.25.2
Summary
In this release, the setDefaultDimensions method in the Metrics utility now emits a warning if an existing default dimension is over-written, making it consistent with addDimension and addDimensions methods:
⭐ Congratulations to @kawaaaa, and @shrivarshapoojari for their first PRs merged in the project 🎉
Changes
- improv(ci): Inherited the secrets for update ssm workflow (#4388) by @sdangol
- feat(event-handler): add resolution logic to base router (#4349) by @svozza
- improv(ci): Fixed the Make Release workflow permission issue (#4385) by @sdangol
- chore(commons): concatenate PT UA to AWS_SDK_UA_APP_ID when one is set (#4374) by @dreamorosi
- improv(ci): Moved the secrets expanded in the run block to env variables (#4370) by @sdangol
- improv(ci): removed the secret inheritance and replaced with the needed secrets (#4364) by @sdangol
- improv(ci): Added comments in workflow files triggering Excessive Secret Exposure Alert (#4367) by @sdangol
- improv(ci): Automate the layer version tracking during the Make Release workflow (#4355) by @sdangol
- refactor(logger): use vitest env helpers in unit tests (#4360) by @dwrth
- chore(parameters): fix SonarQube code quality issues and optimize imports (#4359) by @shrivarshapoojari
- refactor(logger): mark private members as readonly and fix code quality issues (#4350) by @kawaaaas
- ci: switch e2e env in run-e2e-tests workflow (#4347) by @dreamorosi
- improv(metrics): emit warning when default dimensions are overwritten (#4287) by @uttam282005
- improv: decorate methods without destructuring args (#4345) by @dreamorosi
- feat(event-handler): add function to convert Lambda proxy event to web response object (#4343) by @svozza
- fix(event-handler): pass event, context and request objects into handler (#4329) by @svozza
- ci: add Kiro & other LLM fodlers to gitignore (#4333) by @dreamorosi
📜 Documentation updates
- chore(deps): bump tsx from 4.20.4 to 4.20.5 (#4379) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4376) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 52 updates (#4378) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.17 to 9.6.18 in /docs (#4372) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
405aeb6to1a4e939in /docs (#4371) by @dependabot[bot] - improv(ci): Automate the SSM Parameter Update step of the release workflow (#4356) by @sdangol
- chore(deps): bump mkdocs-material from 9.6.16 to 9.6.17 in /docs (#4358) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
bb7b015to405aeb6in /docs (#4354) by @dependabot[bot] - chore(deps): bump the aws-sdk-v3 group across 1 directory with 5 updates (#4352) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4351) by @dependabot[bot]
- chore(deps): bump @types/node from 24.2.1 to 24.3.0 (#4344) by @dependabot[bot]
- chore(ci): update layer ARN on documentation (#4337) by @svozza
🔧 Maintenance
- chore(deps-dev): bump zod from 4.0.17 to 4.1.1 (#4380) by @dependabot[bot]
- chore(deps): bump tsx from 4.20.4 to 4.20.5 (#4379) by @dependabot[bot]
- chore(deps-dev): bump typedoc from 0.28.10 to 0.28.11 in the typescript group across 1 directory (#4377) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4376) by @dependabot[bot]
- chore(deps-dev): bump @biomejs/biome from 2.2.0 to 2.2.2 (#4381) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 52 updates (#4378) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.17 to 9.6.18 in /docs (#4372) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
405aeb6to1a4e939in /docs (#4371) by @dependabot[bot] - improv(ci): Automate the SSM Parameter Update step of the release workflow (#4356) by @sdangol
- chore(deps): bump github/codeql-action from 3.29.10 to 3.29.11 (#4368) by @dependabot[bot]
- chore(deps-dev): bump @redis/client from 5.8.1 to 5.8.2 (#4362) by @dependabot[bot]
- chore(deps): bump actions/dependency-review-action from 4.7.1 to 4.7.2 (#4361) by @dependabot[bot]
- chore(deps): bump mkdocs-material from 9.6.16 to 9.6.17 in /docs (#4358) by @dependabot[bot]
- chore(deps-dev): bump protobufjs from 7.5.3 to 7.5.4 (#4357) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
bb7b015to405aeb6in /docs (#4354) by @dependabot[bot] - chore(deps): bump github/codeql-action from 3.29.9 to 3.29.10 (#4353) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 5 updates (#4352) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4351) by @dependabot[bot]
- chore(deps): bump @types/node from 24.2.1 to 24.3.0 (#4344) by @dependabot[bot]
- chore(deps-dev): bump @biomejs/biome from 2.1.4 to 2.2.0 (#4341) by @dependabot[bot]
This release was made possible by the following contributors:
@dependabot[bot], @dreamorosi, @dwrth, @github-actions[bot], @kawaaaas, @sdangol, @shrivarshapoojari, @svozza, @uttam282005, dependabot[bot] and github-actions[bot]
v2.25.1
Summary
This is a patch release that addresses an issue with the logger and the idempotency package introduced in v2.25.0 that could potentially affect users’ tests in some circumstances. This does not affect any production workloads.
Furthermore, it also fixes an issue with the tracer package which caused a deprecation warning when @tracer.captureLambdaHandler() was used.
We recommend updating to this version if you're currently using v2.25.0, especially if you're experiencing any test-related issues.
⭐ Congratulations @MaxOpperman, @BeckettFrey for their first PRs merged in the project 🎉
Changes
- ci: bump version-n-release GitHub Action and modify input values (#4330) by @dreamorosi
- improv(idempotency): Prevent error when AWS_LAMBDA_FUNCTION_NAME is not passed in the Idempotency Persistence Layer (#4327) by @sdangol
- improv(logger): resolve issue when no logger region is set (#4319) by @MaxOpperman
- improv(ci): Skip Layer version checks for the Gamma environment (#4321) by @sdangol
- refactor: idempotency env service to functions 4246 (#4314) by @BeckettFrey
- fix(tracer): pass args of decorated method as they are (#4312) by @dreamorosi
📜 Documentation updates
- chore(ci): update layer ARN on documentation (#4337) by @svozza
- docs: add FraudFalcon customer reference (#4332) by @dreamorosi
- chore(deps): bump esbuild from 0.25.8 to 0.25.9 (#4325) by @dependabot[bot]
- chore(deps): bump tsx from 4.20.3 to 4.20.4 (#4313) by @dependabot[bot]
🔧 Maintenance
- docs: add FraudFalcon customer reference (#4332) by @dreamorosi
- chore(deps): bump esbuild from 0.25.8 to 0.25.9 (#4325) by @dependabot[bot]
- chore(deps-dev): bump @redis/client from 5.8.0 to 5.8.1 (#4324) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.29.8 to 3.29.9 (#4315) by @dependabot[bot]
- chore(deps): bump tsx from 4.20.3 to 4.20.4 (#4313) by @dependabot[bot]
This release was made possible by the following contributors:
@BeckettFrey, @MaxOpperman, @dependabot[bot], @dreamorosi, @github-actions[bot], @sdangol, @svozza, dependabot[bot] and github-actions[bot]
v2.25.0
Summary
We have discontinued support for Node.js 18 with this release. All users are strongly encouraged to upgrade to Node.js 20 or later to ensure continued compatibility and security updates.
The parse function is now exported from the Parser package. This addition enables manual parsing in scenarios such as validating query string parameters, offering more flexibility in data handling and validation.
We’ve also fixed a bug with the Zod schema for the Cognito Trigger Event in the parser.
Furthermore, we have been working on the improvements in the overall code quality and maintainability of the codebase.
⭐ Congratulations @dwrth, @bdellegrazie, @jaimellamasi for their first PRs merged in the project 🎉
Parse Function
import { parse } from '@aws-lambda-powertools/parser';
export const handler = async (event: APIGatewayEvent) => {
try {
const querySchema = z.object({
id: z.string()
});
const params = parse(event.queryStringParameters, undefined, querySchema);
} catch(error) {
console.error("Failed to parse the query string parameters");
}
}Before this release, it was only possible to use the parser through middleware or a decorator.
To use the parse function, simply pass the payload to be parsed, the envelope (if required), the schema, and the optional safe parse flag.
Changes
- feat(event-handler): add event handler registry (#4307) by @svozza
- feat(event-handler): add error classes for http errors (#4299) by @svozza
- feat(parser): Exported the parse function from the parser (#4300) by @sdangol
- feat(event-handler): implement route matching & resolution system for rest handler (#4297) by @svozza
- refactor(idempotency): fix code quality issues (#4298) by @dwrth
- improv(deps): Decrease the update schedule of aws-cdk and aws-sdk-v3 group in dependabot (#4290) by @sdangol
- refactor(commons): fix code quality issues (#4292) by @dwrth
- refactor(jmespath): fix code quality issues (#4286) by @dwrth
- refactor(batch): improve code quality in test handlers (#4281) by @dwrth
- refactor(logger): replace EnvironmentVariablesService class with helper functions (#4251) by @jaimellamasi
- test(event-handler): coverage 100% for AppSync GraphQL (#4261) by @dreamorosi
- refactor(kafka): improve tests & error handling (#4262) by @dreamorosi
- refactor(tracer): fix code quality issues (#4264) by @dwrth
- fix(parser): cognito schema
preferredRolemay be null (#4259) by @bdellegrazie - ci: update version-n-changelog action & input (#4258) by @dreamorosi
- feat(event-handler): add support for AppSync GraphQL batch resolvers (#4218) by @arnabrahman
📜 Documentation updates
- chore(deps): Bumped the version to 2.25.0 (#4310) by @sdangol
- improv(ci): Verify Output of Layer Deployment (Partitions) GitHub Action (#4308) by @sdangol
- chore(deps): bump @types/node from 24.2.0 to 24.2.1 (#4304) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 34 updates (#4305) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.209.1 to 2.210.0 in the aws-cdk group across 1 directory (#4285) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4294) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4284) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4278) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.3.0 to 0.3.1 in /docs (#4277) by @dependabot[bot]
- docs: update maintainers & PR template (#4274) by @dreamorosi
- chore(deps): bump @types/node from 24.1.0 to 24.2.0 (#4271) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 10 updates (#4270) by @dependabot[bot]
- chore(deps): bump the typescript group across 1 directory with 2 updates (#4268) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4244) by @dependabot[bot]
- chore: drop Node.js 18 support (#4243) by @dreamorosi
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4241) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.207.0 to 2.208.0 in the aws-cdk group across 1 directory (#4237) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
0bfdba4tobb7b015in /docs (#4224) by @dependabot[bot] - chore(deps): bump mkdocs-material from 9.6.15 to 9.6.16 in /docs (#4230) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4232) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4209) by @dependabot[bot]
🔧 Maintenance
- chore(deps): Bumped the version to 2.25.0 (#4310) by @sdangol
- improv(ci): Verify Output of Layer Deployment (Partitions) GitHub Action (#4308) by @sdangol
- chore(deps): bump actions/checkout from 4.2.2 to 5.0.0 (#4301) by @dependabot[bot]
- chore(deps): bump @types/node from 24.2.0 to 24.2.1 (#4304) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 34 updates (#4305) by @dependabot[bot]
- chore(deps-dev): bump the typescript group across 1 directory with 2 updates (#4303) by @dependabot[bot]
- chore(deps-dev): bump zod from 4.0.15 to 4.0.17 (#4302) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 32 updates (#4296) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.209.1 to 2.210.0 in the aws-cdk group across 1 directory (#4285) by @dependabot[bot]
- chore(deps-dev): bump lint-staged from 16.1.4 to 16.1.5 (#4295) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.29.7 to 3.29.8 (#4293) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4294) by @dependabot[bot]
- chore(deps-dev): bump @biomejs/biome from 2.1.3 to 2.1.4 (#4289) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4284) by @dependabot[bot]
- chore(deps): bump actions/download-artifact from 4.3.0 to 5.0.0 (#4280) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4278) by @dependabot[bot]
- chore(deps-dev): bump zod from 4.0.14 to 4.0.15 (#4279) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.3.0 to 0.3.1 in /docs (#4277) by @dependabot[bot]
- chore(deps-dev): bump @redis/client from 5.7.0 to 5.8.0 (#4276) by @dependabot[bot]
- chore(deps-dev): bump lint-staged from 16.1.2 to 16.1.4 (#4275) by @dependabot[bot]
- chore(deps): bump aws-actions/configure-aws-credentials from 4.2.1 to 4.3.1 (#4272) by @dependabot[bot]
- docs: update maintainers & PR template (#4274) by @dreamorosi
- chore(deps): bump @types/node from 24.1.0 to 24.2.0 (#4271) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 10 updates (#4270) by @dependabot[bot]
- chore(deps): bump the typescript group across 1 directory with 2 updates (#4268) by @dependabot[bot]
- chore(deps): update typedoc to v0.28.9 (#4267) by @svozza
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4244) by @dependabot[bot]
- chore: drop Node.js 18 support (#4243) by @dreamorosi
- chore(deps-dev): bump @redis/client from 5.6.1 to 5.7.0 (#4242) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4241) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.207.0 to 2.208.0 in the aws-cdk group across 1 directory (#4237) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.29.4 to 3.29.5 (#4236) by @dependabot[bot]
- test(parser): Fixed failing tests after zod version bump to 4.0.14 (#4240) by @sdangol
- chore(deps-dev): bump @biomejs/biome from 2.1.2 to 2.1.3 (#4238) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
0bfdba4tobb7b015in /docs (#4224) by @dependabot[bot] - chore(deps): bump mkdocs-material from 9.6.15 to 9.6.16 in /docs (#4230) by @[dependabot[bot]](https://github.com/ap...
v2.24.1
Summary
In this release we have improved runtime validations in the Metrics utility, ensuring that invalid metrics are not sent to CloudWatch and avoiding data loss.
Furthermore, we now only support Zod 4.x. Using Zod 3.x with the Parser utility will result in a build-time error.
⭐ Congratulations @JonkaSusaki and @uttam282005 for their first PRs merged in the project 🎉
Metrics Runtime Validations
Before this release, if you published invalid metrics they could fail silently, leading to data loss. Now Lambda will throw an error if the following constraints do not hold:
- Metric Name: Validated according to CloudWatch constraints
- Metric Value: Validated for numeric values
- Metric Unit: Validated for allowed units
- Metric Resolution: Validated for allowed resolutions
- Dimension Name: Both Dimension name and value are validated for non empty, non-null values.
Changes
- fix(metrics): revert changes when raise warning with overridden default dimensions (#4226) by @svozza
- fix(metrics): emit warning when default dimensions are overwritten (#4222) by @uttam282005
- refactor(event-handler): replace EnvironmentVariablesService class with helper functions in Event Handler (#4225) by @JonkaSusaki
- ci: fix version output interpolation in make-version workflow (#4220) by @dreamorosi
- ci: set version number correctly when versioning (#4219) by @dreamorosi
- feat(event-handler): add route management system for ApiGw event handler (#4211) by @svozza
- ci: update
make-release.ymlworkflow to use latest upstream (#4215) by @dreamorosi - ci: remove local create-pr action (#4213) by @dreamorosi
- improv(maintenance): Removed some unused assignments and added missing error handling (#4208) by @sdangol
- ci: remove
lerna version(#4201) by @dreamorosi - refactor(ci): Updated the publish command in the CI to use
npm publishinstead oflerna publish(#4195) by @sdangol - refactor(metrics): replace EnvironmentVariablesService with cached #envConfig (#4188) by @uttam282005
- improv(metrics): Added runtime validations for the metrics utility functions (#4181) by @sdangol
- refactor(parameters): replace EnvironmentVariablesService class with helper functions in Parameters (#4168) by @JonkaSusaki
🌟New features and non-breaking changes
- feat(event-handler): add base router class (#3972) by @dreamorosi
📜 Documentation updates
- chore(ci): bump version to 2.24.1 (#4231) by @sdangol
- chore(deps): bump @types/aws-lambda from 8.10.150 to 8.10.152 (#4205) by @dependabot[bot]
- chore(deps): bump esbuild from 0.25.6 to 0.25.8 (#4200) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 2 updates (#4192) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.14 to 24.1.0 (#4193) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4186) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4183) by @dependabot[bot]
- docs: update release steps in maintainers section (#4180) by @svozza
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4178) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.2.0 to 0.3.0 in /docs (#4175) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.204.0 to 2.205.0 in the aws-cdk group across 1 directory (#4173) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.13 to 24.0.14 (#4174) by @dependabot[bot]
🔧 Maintenance
- chore(ci): bump version to 2.24.1 (#4231) by @sdangol
- chore(deps): bump @types/aws-lambda from 8.10.150 to 8.10.152 (#4205) by @dependabot[bot]
- chore(deps-dev): bump @redis/client from 5.6.0 to 5.6.1 (#4207) by @dependabot[bot]
- chore(deps): Removed the lerna dependency and all the usage of it (#4202) by @sdangol
- chore(deps): bump @aws-sdk/client-lambda from 3.848.0 to 3.851.0 in the aws-sdk-v3 group across 1 directory (#4199) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.29.3 to 3.29.4 (#4198) by @dependabot[bot]
- chore(deps): bump esbuild from 0.25.6 to 0.25.8 (#4200) by @dependabot[bot]
- fix(parser): set zod peer range to 4.x (#4196) by @dreamorosi
- chore(deps): bump github/codeql-action from 3.29.2 to 3.29.3 (#4194) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 2 updates (#4192) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.14 to 24.1.0 (#4193) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4186) by @dependabot[bot]
- chore(deps-dev): bump @biomejs/biome from 2.1.1 to 2.1.2 (#4187) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4183) by @dependabot[bot]
- docs: update release steps in maintainers section (#4180) by @svozza
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4178) by @dependabot[bot]
- chore(deps): bump mkdocs-llmstxt from 0.2.0 to 0.3.0 in /docs (#4175) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.204.0 to 2.205.0 in the aws-cdk group across 1 directory (#4173) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.13 to 24.0.14 (#4174) by @dependabot[bot]
This release was made possible by the following contributors:
@JonkaSusaki, @dependabot[bot], @dreamorosi, @github-actions[bot], @sdangol, @svozza, @uttam282005, dependabot[bot] and github-actions[bot]
v2.24.0
Summary
We’ve listened to your feedback and starting from this release of Parser we support only Zod v4 for all our built-in schemas and envelopes. Additionally the utility got a power up and it now supports schemas written using Standard Schema 🔥.
We’ve also fixed a bug in Tracer that prevented requests made via proxies to be traced correctly and another bug in Metrics that caused dimension sets to be added correctly to the metrics data object..
🌟 Congratulations to @chetan9518, @sdangol, and @matteofigus for their first PRs merged in the project 🎉
Using Parser with Standard Schema
You can now use schemas written using Valibot or other Standard Schema-compatible parsing library to parse incoming events using the parser Middy.js middleware or TypeScript class method decorator. This is useful if your codebase is already relying on one of these libraries or you want to have full control over the bundle size.
Note that our built-in schemas and envelopes are still defined only using Zod. If you would like us to support other libraries like Valibot please open an issue and we will consider it based on the community's feedback.
If you are using Zod v3 and need more time to migrate, you can continue using Parser v2.23.0 as long as needed.
import { Logger } from '@aws-lambda-powertools/logger';
import { parser } from '@aws-lambda-powertools/parser/middleware';
import middy from '@middy/core';
import {
array,
number,
object,
optional,
pipe,
string,
toMinValue,
} from 'valibot';
const logger = new Logger();
const orderSchema = object({
id: pipe(number(), toMinValue(0)),
description: string(),
items: array(
object({
id: pipe(number(), toMinValue(0)),
quantity: pipe(number(), toMinValue(1)),
description: string(),
})
),
optionalField: optional(string()),
});
export const handler = middy()
.use(parser({ schema: orderSchema }))
.handler(async (event): Promise<void> => {
for (const item of event.items) {
logger.info('Processing item', { item });
}
});Tracing requests using a proxy
You can now correctly trace outbound requests made via proxies. Tracer will detect the CONNECT request made to the proxy and intelligently exclude it from the trace data, leaving only the segment for the main request to avoid creating noise in your traces.
import { Tracer } from "@aws-lambda-powertools/tracer";
import { getSecret } from "@aws-lambda-powertools/parameters/secrets";
import { captureLambdaHandler } from "@aws-lambda-powertools/tracer/middleware";
import middy from "@middy/core";
import { ProxyAgent } from "undici";
const tracer = new Tracer({
serviceName: "tracerproxy",
});
const client = new ProxyAgent({
uri: "http://proxy:8080",
token: await getSecret('/dev/proxy-token'),
});
export const handler = middy()
.use(captureLambdaHandler(tracer))
.handler(async () => {
try {
const res = await fetch("https://foo.com", {
dispatcher: client,
signal: AbortSignal.timeout(2000),
});
console.debug("Response status:", res.status);
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
} catch (error) {
console.error("Error fetching URL:", error);
if (error instanceof HttpError) {
return {
statusCode: error.code,
};
}
return {
statusCode: 500,
};
}
return {
statusCode: 200,
};
});Adding dimension sets to metrics
You can create separate dimension sets for your metrics using the addDimensions() method. This allows you to group metrics by different dimension combinations.
Starting from this release, when you use this method, we’ll create a new dimension set rather than adding to the existing dimensions - the previous behavior was incorrect and didn’t allow you to track the same metric across different dimension combinations.
import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics';
const metrics = new Metrics({
namespace: 'serverlessAirline',
serviceName: 'orders',
});
export const handler = async (
_event: unknown,
_context: unknown
): Promise<void> => {
// Add a single dimension
metrics.addDimension('environment', 'prod');
// Add a new dimension set
metrics.addDimensions({
dimension1: '1',
dimension2: '2',
});
// Add another dimension set
metrics.addDimensions({
region: 'us-east-1',
category: 'books',
});
// Add metrics
metrics.addMetric('successfulBooking', MetricUnit.Count, 1);
metrics.publishStoredMetrics();
};Changes
- fix(parser): Removed the nullable type from the md5OfMessageAttributes in SqsRecordSchema (#4165) by @sdangol
- chore(parser): remove deprecated parser type (#4154) by @dreamorosi
- refactor(metrics): optimize
addDimensionsmethod to avoid O(n²) complexity (#4156) by @dreamorosi - chore: fix typo in partitioned layers workflow (#4126) by @dreamorosi
🌟New features and non-breaking changes
- feat(event-handler): add base router class (#3972) by @dreamorosi
📜 Documentation updates
- chore: bump to 2.24.0 (#4172) by @dreamorosi
- chore(deps): bump @types/node from 24.0.12 to 24.0.13 (#4167) by @dependabot[bot]
- chore(deps): bump esbuild from 0.25.5 to 0.25.6 (#4166) by @dependabot[bot]
- feat(parser): support Standard Schema and upgrade to Zod v4 (#4164) by @dreamorosi
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4159) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.10 to 24.0.12 (#4157) by @dependabot[bot]
- chore(batch): exclude deprecated code from coverage (#4152) by @dreamorosi
- docs(idempotency): simplify snippets (#4150) by @dreamorosi
- fix(tracer): skip tracing CONNECT requests (#4148) by @dreamorosi
- chore(deps): bump aws-cdk-lib from 2.203.1 to 2.204.0 in the aws-cdk group across 1 directory (#4143) by @dependabot[bot]
- chore: bump biome formatter to next major & reformat (#4145) by @dreamorosi
- docs: update roadmap with completed features and Discord badge (#4133) by @dreamorosi
- chore(deps): bump the aws-cdk group across 1 directory with 2 updates (#4129) by @dependabot[bot]
- fix(metrics): addDimensions() documentation and tests (#3964) by @matteofigus
- chore(deps): bump @types/node from 24.0.8 to 24.0.10 (#4119) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4118) by @dependabot[bot]
🐛 Bug and hot fixes
- fix(metrics): addDimensions() documentation and tests (#3964) by @matteofigus
🔧 Maintenance
- chore: bump to 2.24.0 (#4172) by @dreamorosi
- chore(deps): bump @types/node from 24.0.12 to 24.0.13 (#4167) by @dependabot[bot]
- chore(deps): bump esbuild from 0.25.5 to 0.25.6 (#4166) by @dependabot[bot]
- feat(parser): support Standard Schema and upgrade to Zod v4 (#4164) by @dreamorosi
- chore(deps-dev): bump @redis/client from 5.5.6 to 5.6.0 (#4162) by @dependabot[bot]
- chore(deps): bump the aws-sdk-v3 group across 1 directory with 9 updates (#4159) by @dependabot[bot]
- chore(deps): bump vscode/devcontainers/javascript-node from
0d29e5ftoeac37fbin /.devcontainer (#4161) by @dependabot[bot] - chore(deps-dev): bump zod from 3.25.67 to 3.25.76 (#4158) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.10 to 24.0.12 (#4157) by @dependabot[bot]
- refactor(tracer): replace class-based env access with functional helpers (#4146) by @chetan9518
- chore(deps): bump aws-cdk-lib from 2.203.1 to 2.204.0 in the aws-cdk group across 1 directory (#4143) by @dependabot[bot]
- chore(deps-dev): bump @biomejs/biome from 1.9.4 to 2.1.0 (#4147) by @dependabot[bot]
- chore: bump biome formatter to next major & reformat (#4145) by @dreamorosi
- chore(deps): bump the aws-cdk group across 1 directory with 2 updates (#4129) by @dependabot[bot]
- chore(deps): bump @types/node from 24.0.8 to 24.0.10 (#4119) by @dependabot[bot]
- chore(deps): bump the aws-cdk group across 1 directory with 3 updates (#4118) by @dependabot[bot]
- chore(deps-dev): bump @aws-sdk/client-cloudwatch from 3.840.0 to 3.841.0 in the aws-sdk-v3 group across 1 directory (#4117) by @[dependabot[bot]](http...