An easy way to deploy a regular application to AWS Lambda
Greetings, everyone.
In this article, we'll introduce an easy way to deploy applications built with frameworks that have built-in server functionality to AWS Lambda!
What We'll Use#
The star of the show is aws-lambda-web-adapter!
AWS Lambda Web Adapter runs as an internal extension on AWS Lambda and has reverse proxy functionality that converts AWS Lambda responses into HTTP requests.
- HTTP application you want to deploy → Simply place it at the AWS Lambda entry point
- AWS Lambda Web Adapter → Receives events + forwards HTTP requests
Also, to support various languages and runtimes, we'll use an example of creating a Lambda function with an OCI container image.
Preparing the Web Application#
In this example, we'll write the application using FastAPI + uvicorn.
Setup#
We'll use uv for virtual environment management. Let's add the necessary packages.
uv init
uv add fastapi uvicornApplication Code#
The main application code will be very simple.
GET /→ Returns a fixed valuePOST /events→ Returns the received Event JSON as-is.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def greet():
return {"message": "Hello, World!"}
@app.post("/events")
def read_event(event: dict):
return eventAlso, to enable module recognition, create src/__init__.py as an empty file.
About Non-HTTP Request Events#
AWS Lambda Web Adapter can also receive non-HTTP Lambda events, and by default, these events are forwarded to POST /events. Using this, you can easily convert batch servers to Lambda as well.
- HTTP requests (API Gateway, Function URLs, etc.) → Same method and path
- Non-HTTP requests (SQS, SNS, custom events, etc.) → Request to POST
/events
Note that the event request path can be changed via configuration (environment variables).
Deploying to AWS Lambda#
Creating the Image#
Let's create an image for deploying to AWS Lambda. In line 2, we're adding AWS Lambda Web Adapter as an extension.
Also, the entry point doesn't need to be the AWS Lambda RIC entry point but can be the main web application, which is very intuitive.
FROM ghcr.io/astral-sh/uv:python3.12-alpine
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.1 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_LWA_PORT=8000
WORKDIR /var/task
ENV PYTHONPATH=/var/task
COPY ./src ./src
COPY ./pyproject.toml ./uv.lock ./
RUN uv sync
ENV UV_CACHE_DIR=/tmp/uv
CMD ["uv", "run", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
Tag the created image and push it to ECR.
Deploying and Testing on AWS Lambda#
No special steps are required; it's already in a state where it can be deployed to AWS Lambda.
Let's verify by sending a GET / request from an API Gateway Http API event.
Let's also check with Function URLs.
Let's also send a non-HTTP event. This event is working correctly because we configured it to echo on POST /events!
Summary#
Using AWS Lambda Web Adapter, we were able to deploy to AWS Lambda without changing the application code!
However, for frameworks that take time to start up, such as Spring, considerations such as configuring Provisioned concurrency are necessary.