AWS Lambda

AWS Lambda compatibility

srvx provides an AWS Lambda compatibility adapter that handles all the necessary transformations between AWS Lambda's event format and standard web Request/Response objects.

To use the AWS Lambda adapter, import the toLambdaHandler function from "srvx/aws-lambda":

server.ts
import { toLambdaHandler } from "srvx/aws-lambda";
import { serveStatic } from "srvx/static";

export const handler = toLambdaHandler({
  middleware: [serveStatic({ dir: "public" })],
  fetch(req: Request) {
    return Response.json({ hello: "world!" });
  },
});

The toLambdaHandler function accepts a ServerOptions object as its parameter (see Server Options for details). However, since this is a serverless environment, options related to the server instance like host and port are not respected and will be ignored.

You can find a complete example of AWS Lambda in the examples/aws-lambda directory.

Serving Static Assets

The example above uses serveStatic middleware to serve static files directly from the Lambda function. While this works for simple use cases, it comes with limitations:

  • Lambda has a deployment package size limit (50MB zipped, 250MB unzipped)
  • Each static file request incurs Lambda invocation costs
  • Cold starts affect static file delivery latency

For production applications, consider these alternatives:

  • Amazon S3 + CloudFront: Store static assets in S3 and serve them through CloudFront CDN for better performance and lower costs
  • API Gateway Binary Support: Configure API Gateway to serve static files directly from S3 without invoking Lambda
  • Separate Static Hosting: Use dedicated static hosting services (Vercel, Netlify, or S3 static website hosting) for your assets

Invoking Lambda Handlers

The invokeLambdaHandler utility allows you to invoke an AWS Lambda handler using standard Web Request/Response objects. This is useful for testing your Lambda handlers locally or integrating them into other web-based workflows.

import { toLambdaHandler, invokeLambdaHandler } from "srvx/aws-lambda";

const handler = toLambdaHandler({
  fetch(req: Request) {
    return Response.json({ hello: "world!" });
  },
});

// Invoke the handler with a standard Request
const request = new Request("https://example.com/api");
const response = await invokeLambdaHandler(handler, request);

console.log(await response.json()); // { hello: "world!" }

The function handles all conversions internally:

Converts the Web Request to an AWS Lambda event (compatible with both v1 and v2 API Gateway formats)

Invokes the Lambda handler with a mock context

Converts the AWS Lambda result back to a standard Web Response

Response Streaming

AWS Lambda supports response streaming which allows you to send response data progressively as it becomes available. This improves Time To First Byte (TTFB) and enables streaming large responses (up to 20MB vs 6MB buffered limit).

To use response streaming, wrap your handler with awslambda.streamifyResponse() and use handleLambdaEventWithStream:

import { handleLambdaEventWithStream, type AWSLambdaStreamingHandler } from "srvx/aws-lambda";

const fetchHandler = async (request: Request) => {
  // Create a streaming response
  const stream = new ReadableStream({
    async start(controller) {
      controller.enqueue(new TextEncoder().encode("Hello, "));
      await new Promise((r) => setTimeout(r, 100));
      controller.enqueue(new TextEncoder().encode("streaming "));
      await new Promise((r) => setTimeout(r, 100));
      controller.enqueue(new TextEncoder().encode("world!"));
      controller.close();
    },
  });

  return new Response(stream, {
    headers: { "Content-Type": "text/plain" },
  });
};

// Export a streaming handler
export const handler: AWSLambdaStreamingHandler = awslambda.streamifyResponse(
  (event, responseStream, context) =>
    handleLambdaEventWithStream(fetchHandler, event, responseStream, context),
);
Response streaming requires a Lambda Function URL with --invoke-mode RESPONSE_STREAM or the InvokeWithResponseStream API. It does not work with API Gateway or Application Load Balancer for progressive streaming.