Greetings, everyone.
Today, I'll introduce a simple way to deploy applications built with frameworks that have built-in server functionality to AWS Lambda!
What We'll Use#
The star of today's show is aws-lambda-web-adapter!
AWS Lambda Web Adapter works as an internal extension on AWS Lambda and functions as a reverse proxy that converts AWS Lambda responses to HTTP requests.
- HTTP application you want to deploy → Just place it at the entry point of AWS Lambda
- AWS Lambda Web Adapter → Receives events + forwards HTTP requests
Also, to provide versatility for various languages and runtimes, we'll use an OCI container image to create the Lambda function in this example.
Preparing the Web Application Part#
This time, we'll write the application part using FastAPI + uvicorn.
Preparation#
We'll use uv for virtual environment management. Let's add the necessary packages.
uv init
uv add fastapi uvicorn
Application Code#
We'll keep the main application code 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 event
Also, to recognize the module, create an empty file src/__init__.py
.
About Non-HTTP Request Events#
AWS Lambda Web Adapter can receive non-HTTP Lambda events, and by default, these events are forwarded to POST /events
. This means you can easily Lambda-ify batch servers 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 request path for Events can be changed through configuration (environment variables).
Deploying to AWS Lambda#
Creating the Image#
We'll create an image for deployment to AWS Lambda. In the second line, we add AWS Lambda Web Adapter as an extension.
Also, the entry point can be the main web application part rather than the AWS Lambda RIC entry point, making it 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 procedures are needed, as it's already ready to be deployed to AWS Lambda.
We'll verify by configuring an API Gateway Http API event to send a GET / request.
Let's also check with Function URLs.
Additionally, let's send a non-HTTP event. This event is working properly because we set it to echo in 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 like Provisioned concurrency settings may be necessary.