Lightweight web framework for your serverless applications
Lightweight web framework for your serverless applications
Lambda API is a lightweight web framework for AWS Lambda using AWS API Gateway Lambda Proxy Integration or ALB Lambda Target Support. This closely mirrors (and is based on) other web frameworks like Express.js and Fastify, but is significantly stripped down to maximize performance with Lambda's stateless, single run executions.
lambda-api@v1 is using AWS SDK v3. If you are using AWS SDK v2, please use [email protected].
// Require the framework and instantiate it
const api = require('lambda-api')();
// Define a route
api.get('/status', async (req, res) => {
return { status: 'ok' };
});
// Declare your Lambda handler
exports.handler = async (event, context) => {
// Run the request
return await api.run(event, context);
};For a full tutorial see How To: Build a Serverless API with Serverless, AWS Lambda and Lambda API.
Express.js, Fastify, Koa, Restify, and Hapi are just a few of the many amazing web frameworks out there for Node.js. So why build yet another one when there are so many great options already? One word: DEPENDENCIES.
These other frameworks are extremely powerful, but that benefit comes with the steep price of requiring several additional Node.js modules. Not only is this a bit of a security issue (see Beware of Third-Party Packages in Securing Serverless), but it also adds bloat to your codebase, filling your node_modules directory with a ton of extra files. For serverless applications that need to load quickly, all of these extra dependencies slow down execution and use more memory than necessary. Express.js has 30 dependencies, Fastify has 12, and Hapi has 17! These numbers don't even include their dependencies' dependencies.
Lambda API ships with ZERO required dependencies. None. Zip. Zilch. The only extras are the AWS SDK v3 S3 packages (@aws-sdk/client-s3 and @aws-sdk/s3-request-presigner), declared as optional peer dependencies. They power the built-in S3 file helpers (sendFile(), getLink(), and S3 redirects). Because they're optional, installing Lambda API won't pull them in — npm, pnpm, Yarn, and Bun all skip optional peer dependencies, so your node_modules stays clean unless you install them yourself. And because the S3 client is loaded lazily (only when an S3 helper actually runs), bundlers can safely treat the AWS SDK as external when you don't use those features. See Installation for details.
Lambda API was written to be extremely lightweight and built specifically for SERVERLESS applications using AWS Lambda and API Gateway. It provides support for API routing, serving up HTML pages, issuing redirects, serving binary files and much more. Worried about observability? Lambda API has a built-in logging engine that can even periodically sample requests for things like tracing and benchmarking. It has a powerful middleware and error handling system, allowing you to implement just about anything you can dream of. Best of all, it was designed to work with Lambda's Proxy Integration, automatically handling all the interaction with API Gateway for you. It parses REQUESTS and formats RESPONSES, allowing you to focus on your application's core functionality, instead of fiddling with inputs and outputs.
You may have heard that a serverless "best practice" is to keep your functions small and limit them to a single purpose. I generally agree since building monolith applications is not what serverless was designed for. However, what exactly is a "single purpose" when it comes to building serverless APIs and web services? Should we create a separate function for our "create user" POST endpoint and then another one for our "update user" PUT endpoint? Should we create yet another function for our "delete user" DELETE endpoint? You certainly could, but that seems like a lot of repeated boilerplate code. On the other hand, you could create just one function that handled all your user management features. It may even make sense (in certain circumstances) to create one big serverless function handling several related components that can share your VPC database connections.
Whatever you decide is best for your use case, Lambda API is there to support you. Whether your function has over a hundred routes, or just one, Lambda API's small size and lightning fast load time has virtually no impact on your function's performance. You can even define global wildcard routes that will process any incoming request, allowing you to use API Gateway or ALB to determine the routing. Yet despite its small footprint, it gives you the power of a full-featured web framework.
npm i lambda-api --saveLambda API has no required runtime dependencies. The S3 file helpers (sendFile(), getLink(), and S3 redirects) rely on the AWS SDK v3, which is declared as an optional peer dependency. If you use those features, install the SDK packages alongside Lambda API:
npm i @aws-sdk/client-s3 @aws-sdk/s3-request-presigner --saveIf you don't use the S3 helpers, you can skip this — nothing else in Lambda API touches the AWS SDK. The S3 client is loaded lazily, so even when the SDK is present in your tree, bundlers can mark it as external and leave it out of the bundle.
Releases are published to npm via GitHub Actions using trusted publishing (OIDC), so every published version ships with npm provenance — a signed, verifiable link back to the exact commit and workflow that built it.
Require the lambda-api module into your Lambda handler script and instantiate it. You can initialize the API with the following options:
| Property | Type | Description |
|---|---|---|
| base | String |
Base path for all routes, e.g. base: 'v1' would prefix all routes with /v1 |
| callbackName | String |
Override the default callback query parameter name for JSONP calls |
| logger | boolean or object |
Enables default logging or allows for configuration through a Logging Configuration object. |
| mimeTypes | Object |
Name/value pairs of additional MIME types to be supported by the type(). The key should be the file extension (without the .) and the value should be the expected MIME type, e.g. application/json |
| serializer | Function |
Optional object serializer function. This function receives the body of a response and must return a string. Defaults to JSON.stringify |
| version | String |
Version number accessible via the REQUEST object |
| errorHeaderWhitelist | `Ar |
No open issues yet, or sync has not completed.