Deploying FastAPI app to AWS Lambda with Serverless Framework
Introduction
If you're like me, from time to time you want to just create a simple API and quickly share it with others. FastAPI is a modern, Python-based web framework that allows to build such APIs in a very quick manner. In the article below we will learn how to deploy your FastAPI application on AWS Lambda in a matter of minutes with the help of Serverless Framework.
Prerequisites
We will be using Serverless Framework to build our sample application. As FastAPI is a Python framework, please make sure to have Python installed ahead of time. In the tutorial, we will be using Python 3.9 as our runtime of choice. If you need help setting up Serverless Framework, please refer to getting started guide. Additionally, as we will be using AWS Lambda, you need to have an AWS account. If you're new to both Serverless Framework and AWS, please see the getting started guide that also includes AWS credentials setup.
Setting up a simple FastAPI application
Let's create a new directory for our project called serverless-fastapi
. Then, we will start with a basic FastAPI application in app.py
file in the root of our project:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def hello_world():
return {'message': 'Hello from FastAPI'}
@app.get("/hello/{name}")
def hello(name: str):
return {"message": f'Hello from FastAPI, {name}!'}
Additionally, let's also specify our dependency on FastAPI by creating requirements.txt
file in the root of our project with the following content:
fastapi==0.89.1
Adapting our service for AWS Lambda with Serverless Framework
Now that we have our FastAPI application ready, let's try to deploy it to AWS Lambda.
First of all, we will use a library called mangum, which serves as an adapter between AWS Lambda-specific events and ASGI apps such as FastAPI. First of all, let's add mangum
to our requirements.txt
file:
fastapi==0.89.1
mangum==0.17.0
Now, let's use it to wrap our FastAPI application:
from fastapi import FastAPI
from mangum import Mangum
app = FastAPI()
@app.get("/")
def hello_world():
return {'message': 'Hello from FastAPI'}
@app.get("/hello/{name}")
def hello(name: str):
return {"message": f'Hello from FastAPI, {name}!'}
handler = Mangum(app)
Now that our FastAPI application is Lambda-compatible, let's deploy it to AWS with Serverless Framework! We will start with creating a serverless.yml
file that will serve as a main configuration file for our deployment. Let's create the serverless.yml
file in the root of our project:
service: serverless-fastapi
frameworkVersion: '3'
provider:
name: aws
runtime: python3.9
functions:
api:
handler: app.handler
events:
- httpApi: '*'
The configuration above would deploy a Lambda function that will serve as a handler for incoming requests from an API Gateway, but there's still one issue. By default, Serverless Framework does not handle Python dependencies. Luckily, we can use a very popular serverless-python-requirements
plugin to handle that for us. The serverless-python-requirements
plugin is able to automatically recognize, install, and include all needed dependencies in our Lambda function code artifact. Before using it, we need to install it with npm
(or any other similar package manager). In the process, we will also create package.json
file in our project. We will use that file to manage installations of plugins for Serverless Framework:
npm init -y
npm install --save-dev serverless-python-requirements
We also need to instruct Serverless Framework to use serverless-python-plugin
, we can do that by adding it to the serverless.yml
configuration file:
service: serverless-fastapi
frameworkVersion: '3'
provider:
name: aws
runtime: python3.9
functions:
api:
handler: handler.hello
events:
- httpApi: '*'
plugins:
- serverless-python-requirements
As serverless-python-requirements
automatically recognizes requirements.txt
file in our project, we don't have to do anything extra to ensure proper packaging of our application.
With dependency management out of the way, we're ready to deploy our service:
sls deploy
After the deployment is finished, you should see the output similar to:
✔ Service deployed to stack aws-python-fastapi-dev (51s)
endpoint: ANY - https://xxx.execute-api.us-east-1.amazonaws.com
functions:
api: aws-python-fastapi-dev-api (3.6 MB)
Let's grab the url and try to call our service:
curl https://xxx.execute-api.us-east-1.amazonaws.com
You should see an output similar to this:
{"message":"Hello from FastAPI"}
Now let's try to call the parameterized endpoint:
curl https://xxx.execute-api.us-east-1.amazonaws.com/hello/John
The output should now look like this:
{"message":"Hello from FastAPI, John!"}
Congratulations, we have our first working FastAPI application running in serverless manner on AWS Lambda!
Summary
Over the course of this short tutorial, we were able to adjust a simple FastAPI application and deploy it to AWS Lambda. If you'd like to check out the source code for the final version of the project, it's available here. Thanks for reading!