Library / SDK
middyjs/middy avatar
middyjs/middy

Middy: a middleware engine for AWS Lambda handlers on Node.js

🛵 The stylish Node.js middleware engine for AWS Lambda 🛵

3,904 stars399 forksJavaScriptMIT

At a glance

What is it?
Middy composes parsing, validation, auth, observability and error handling as reusable steps around a Lambda handler. It ships 52 official packages, a tiny core with no AWS SDK, and requires Node.js 24 or newer.
Who is it for?
Adopt Middy if your Lambda handlers are growing past a single function and you keep re-adding body parsing, schema validation, error mapping and structured logging by hand. Skip it for one-off scripts, or if you are pinned below Node.js 24, since the package sets engineStrict and the README states Node.js >= 24.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The repetitive Lambda work Middy removes

A Lambda handler is a function that receives an event and returns a response. In production that function also has to parse a JSON body, validate it against a schema, catch thrown errors and turn them into HTTP status codes rather than stack traces, and emit logs that a log aggregator can read. None of that is the business logic, and all of it gets copied between handlers.

Middy's answer is to keep the handler focused and attach those steps as middleware. The README lists the concerns it expects production handlers to have: input validation at every trust boundary, structured logging, mapped HTTP error responses, secrets and config fetched from a secure store with caching and cold-start prefetch, CORS and security headers, authentication, partial-batch failure handling for SQS, Kinesis, DynamoDB Streams, Kafka and S3 Batch, and graceful pre-timeout responses so a client sees 408 instead of 504.

The audience is Node.js engineers writing AWS Lambda functions, particularly HTTP APIs behind API Gateway and event-source consumers. The README takes a firm position on scope: use Middy for every production Lambda, and treats the tiny single handler as a trap, on the grounds that handlers grow and you do not want to add validation and error mapping under pressure later. That is a vendor's argument, but it is a defensible one, because the cost of a missing schema check is paid at runtime by whoever is on call.

How the middleware chain executes around your handler

Middy is a chain, not a framework with a router at the centre. You call middy(), attach middlewares with .use(), and finish with .handler(), passing the function that holds your business logic. Each middleware can act before the handler runs, after it returns, or when it throws, which is the standard way to express request and response stages.

The core is deliberately small. The README states it depends only on @middy/util, plus an optional peer dependency for durable functions, and that it pulls no AWS SDK into the core. That matters for cold starts and for bundle size: if you only need body parsing and validation, you are not shipping an SDK client you never call. Middlewares for AWS services are separate packages you install individually, which is why the install instructions tell you to add only the ones you need.

The package list covers API Gateway, SQS, S3, DynamoDB, SNS, EventBridge, Kinesis, Kafka and WebSockets, and the project also ships routers for HTTP, WebSocket and CloudFormation custom resources. TypeScript types are built in, and the module format is ESM. Response streaming and durable functions are listed as first-class, which matters because those two features change how a handler returns data and how far a chain can be retried.

Installing Middy and wiring a first validated handler

Installation is a single npm command for the core, followed by one command per middleware. The README gives this exact pair, and the second line installs three middlewares: a JSON body parser, an error handler and a validator.

bash
npm install --save @middy/core
npm install --save @middy/http-json-body-parser @middy/http-error-handler @middy/validator

With the packages in place, the README's example builds a handler that parses the body, validates it against a JSON schema, and maps thrown errors to HTTP responses. The schema is transpiled before it is passed to the validator, and the middleware order is the order in which the steps run.

javascript
import middy from '@middy/core'
import httpJsonBodyParser from '@middy/http-json-body-parser'
import httpErrorHandler from '@middy/http-error-handler'
import validator from '@middy/validator'
import { transpileSchema } from '@middy/validator/transpile'

export const handler = middy()
  .use(httpJsonBodyParser())
  .use(validator({ eventSchema: transpileSchema(schema) }))
  .use(httpErrorHandler())
  .handler(lambdaHandler)

What you should see is a handler that receives a parsed object on event.body rather than a raw string, rejects a request whose body is missing amount or currency before your code runs, and returns a mapped error response instead of an unhandled exception. Full documentation lives at middy.js.org, and the project also publishes llms.txt and llms-full.txt for tooling that reads documentation in that form.

Node.js 24, ESM and the 8.0.0 alpha line

The runtime floor is high. The repository package.json declares engines.node as >=24 with engineStrict set, and the README repeats Node.js >= 24 and ESM. If your functions run on an older Lambda runtime, or your project is still CommonJS, Middy is the wrong tool until you move. This is not a soft recommendation: engineStrict in the manifest turns an unsupported Node.js version into an install-time refusal rather than a runtime surprise.

The version line needs attention too. The most recent release is 8.0.0-alpha.1, published on 2026-09-19, with 8.0.0-alpha.0 on the same day. The latest stable release is 7.9.2 from 2026-08-27. An alpha carries no stability promise, so a team that wants a settled dependency should be on the 7.x line and treat 8.0.0 as something to evaluate separately. The repository itself is not archived and the last push was on 2026-09-19.

The testing setup is unusually strict, and it shapes what you can expect from contributions. The unit test script runs the Node.js test runner with line, branch and function coverage all required at 100 percent, excluding test, fuzz and performance files. A separate SAST script chains license, lockfile, Semgrep, TruffleHog, gitleaks, actionlint, zizmor and Trivy checks. For an adopter this is a signal about release discipline. It is not a signal that the middleware you need already exists.

Where a middleware chain gets in the way

The chain is the cost. Every middleware you attach runs on every invocation, and the README's own advice, to use Middy for every production Lambda, pushes toward a longer chain than any single handler needs. A function that only writes to DynamoDB and is invoked by a scheduler gains nothing from an HTTP body parser, and adding it anyway is pure overhead.

Ordering is the second sharp edge. Because middlewares act before and after the handler, a validator placed after a parser sees a parsed body while one placed before it does not. The README example puts the parser first, and that ordering is load-bearing rather than cosmetic. Debugging a chain also means reading several packages to understand one request, which is a real cost when a handler misbehaves under load.

The README's claim that Middy belongs in every production Lambda is the part I would push back on. It is written by the project, and it argues against the small-handler case by asserting that handlers grow. Sometimes they do not. A scheduled job with no external input and no HTTP response has no trust boundary to validate and no status code to map, and for that handler a plain exported function is easier to read and to test. Middy is a tool for handlers with non-functional concerns, not a default.

Middy against AWS Lambda Powertools and raw handlers

The nearest alternative is AWS Lambda Powertools for TypeScript, which also covers structured logging, tracing and metrics for Lambda. The difference is in shape. Powertools provides utilities you import and call inside your handler, while Middy wraps the handler itself in a chain, so concerns are attached once at export time rather than invoked at each call site. The README links a comparison page at middy.js.org/docs/compare/powertools, and the two are not mutually exclusive: the documentation covers using Middy together with Powertools, which suggests the intended reading is composition rather than replacement.

The other alternative is the raw handler, which the README addresses directly at middy.js.org/docs/compare/raw-lambda. A raw handler has no dependency, no chain to order and nothing to learn. It also has no shared place to put validation, so each handler repeats the same try/catch and the same schema check. Which one wins depends on how many handlers you have. At one or two, raw is simpler. At twenty, the repetition is the problem Middy was built to remove.

Editorial conclusion

Adopt Middy if your Lambda handlers are growing past a single function and you keep re-adding body parsing, schema validation, error mapping and structured logging by hand. Skip it for one-off scripts, or if you are pinned below Node.js 24, since the package sets engineStrict and the README states Node.js >= 24. Before committing, verify the Node.js runtime your functions actually run on, and check whether the middleware you need exists among the 52 official packages rather than assuming you will write it yourself.

Frequently asked questions

What is Middy in the context of AWS Lambda?

Middy is a middleware engine for AWS Lambda on Node.js. It keeps the handler focused on business logic while attaching reusable steps for parsing, validation, auth, observability, error handling and AWS service integration.

How do I install Middy from npm?

The README gives npm install --save @middy/core for the core, then a second command for the middlewares you need, for example @middy/http-json-body-parser, @middy/http-error-handler and @middy/validator.

Which Node.js version does Middy require?

The README states Node.js >= 24 and ESM, and the repository package.json sets engines.node to >=24 with engineStrict enabled, so an older runtime fails at install time.

Does Middy include the AWS SDK in its core?

No. The README describes the core as tiny, depending only on @middy/util plus an optional peer dependency for durable functions, with no AWS SDK in core. AWS service integrations are separate packages.

Is Middy free to use in commercial projects?

The repository is licensed under MIT, which permits commercial use. Read the LICENSE file in the repository for the exact terms rather than relying on a summary.

Official sources

  1. License: MIT
  2. middyjs/middy on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/middyjs-middy.svg)](https://hysenlabs.com/projects/middyjs-middy)