ademoverflow
en
fr

How to deploy your FastAPI application on AWS Lambda with Serverless

Author: Adem Usta

Published on 2021-04-10

How to deploy your FastAPI application on AWS Lambda with Serverless

Introduction

FastAPI, the python package created by Sebastián Ramírez, is a great framework that allows you to create REST APIs.

It’s quite straightforward to take the control of it.

If you didn’t know this package, I wisely invite you to visit the official documentation and create your APIs with it !

If you came accross this article, you are probably looking for a way to deploy your FastAPI application on AWS Lambda, the Amazon serverless ecosystem.

Good pick ! We will try to explain to you how to proceed.

Tutorial

Step 1 - Create a simple FastAPI app

By following the official guide, we can code an application with a few lines of code.

Let’s create a file main.py that declares the app and a /hello route:

from fastapi import FastAPI

app = FastAPI(title="MyAwesomeApp")

@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}

Step 2 - Test your application locally

To test the app locally, let’s create a virtual environment and install what’s inside the requirements.txt file:

fastapi==0.63.0
uvicorn==0.13.4

Some commands to do that:

python3.8 -m venv .virtualenv   # Creates a virtual environment
source .virtualenv/bin/activate # Activates it in the current shell
pip install -r requirements.txt # Installs python packages

Deploy your application locally:

uvicorn main:app

You should see some logs like these:

INFO:     Started server process [87999]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Your app is available here: http://127.0.0.1:8000.

You can check the autogenerated documentation here: http://127.0.0.1:8000/docs

A small overview:

FastAPI autogenerated documentation

Is your app fully functionnal locally ? Perfect, we are ready for the rest.

Step 3 - Adapt your FastAPI application with the AWS Lambda ecosystem

To make your application compatible with Lambda, we will use a small package called Mangum.

Add it in your requirements.txt file, it will be essential in the next steps.

fastapi==0.63.0
uvicorn==0.13.4
mangum==0.11.0

We will modify main.py to wrap up the app object:

from fastapi import FastAPI
from mangum import Mangum

app = FastAPI(title="MyAwesomeApp")

@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}

handler = Mangum(app)

Note:

At this point, the app is ready and will be functionnal with Lambda, but one of the features won’t be accessible: the autogenerated documentation.

Indeed, when deployed, the application will be accessible with an endpoint that has this shape: https://XXXXXXX.execute-api.eu-west-1.amazonaws.com/stage.

Out, to generate the documentation, FastAPI needs, by default, to be served through a domain, not a path.

To solve this problem, we will modify the python code:

import os

from fastapi import FastAPI
from mangum import Mangum

stage = os.environ.get('STAGE', None)
openapi_prefix = f"/{stage}" if stage else "/"

app = FastAPI(title="MyAwesomeApp", openapi_prefix=openapi_prefix) # Here is the magic


@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}


handler = Mangum(app)

In summary:

We changed the path that is used to serve openapi.json, that will allow the documentation page to be generated without any issue.

At this point, your python code is ready ! Let’s deploy that with serverless.

Step 4 - Use serverless to deploy the application

You need to install the serverless CLI and configure it with your AWS credentials.

Install the CLI with npm:

npm install -g serverless

It’s a tool that facilitate the deployment of applications and services in the cloud, by describing them in a YAML file.

It’s compatible with AWS Lambda, and more generally with AWS Cloudformation.

For more info about this tool, go check serverless.com.

Configure serverless with your credentials:

serverless config credentials --provider aws --key <YOUR_KEY> --secret <YOUR_SECRET_KEY>

Let’s create a serverless.yaml file that contains all the specifications of our app:

service: my-awesome-app

package:
  individually: true

provider:
  name: aws
  runtime: python3.8
  region: eu-west-1
  stage: ${opt:stage, "dev"}

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true
    layer:
      name: my-awesome-app-layer
      description: My awesome app layer
      compatibleRuntimes:
        - python3.8

functions:
  app:
    package:
      include:
        - "main.py"
      exclude:
        - "requirements.txt"
        - "package.json"
        - "package-lock.json"
        - ".serverless/**"
        - ".virtualenv/**"
        - "node_modules/**"

    handler: main.handler
    environment:
      STAGE: ${self:provider.stage}
    layers:
      - { Ref: PythonRequirementsLambdaLayer }
    events:
      - http:
          method: any
          path: /{proxy+}

And, at the same level, create a package.json file:

{
    "name": "my-awesome-app",
    "version": "1.0.0",
    "author": "<YOUR_NAME>",
    "dependencies": {
        "serverless-python-requirements": "^5.0.1"
    }
}

This file will help us install some JavaScript plugins that are used in our YAML file.

Install these plugins:

npm install

And, let’s deploy our application !

sls deploy --stage staging # "stage" indicates which stage you are deploying. It could be anything.

serverless does its magic.

After some minutes (no more than 5 usually), you will see some logs like these:

Service Information
service: my-awesome-app
stage: staging
region: eu-west-1
stack: my-awesome-app-staging
resources: 12
api keys:
  None
endpoints:
  ANY - <ENDPOINT HERE>
functions:
  app: my-awesome-app-staging-app
...

By checking these logs, you will find your application endpoint !

Here, it’s https://XXXXXXXXX.execute-api.eu-west-1.amazonaws.com/staging/ (XXXXXX is usually a mix of numbers and letters).

If you visit https://XXXXXXXXX.execute-api.eu-west-1.amazonaws.com/staging/docs, you will see your application documentation !

To update your app (e.g add a new route, etc.), you just need to modify your code, and deploy again:

sls deploy --stage staging

To completely delete your application from the cloud:

sls remove --stage staging

You now have all the information to create FastAPI apps and host them on AWS Lambda !

[Bonus] Step 5 - Use your own domain with your app

If you want your application to be available through your own domain, you’re a few steps from doing it !

Some prerequisites are necessary:

  • a domain name hosted on AWS Route53
  • a certificate linked to this domain (for HTTPS), generated with AWS Certificate Manager (if you don’t have it, create a new one and host it on the AWS default region us-east-1, as it is considered as global for certificates).

We will use a plugin to make our life easier: serverless-domain-manager.

Install it:

npm install serverless-domain-manager

Add it in the list of plugins, in your serverless.yaml file:

plugins:
  - serverless-python-requirements
  - serverless-domain-manager

We need to configure the plugin, so add these few lines in the custom section of serverless.yaml:

custom:
  customDomain:
    domainName: YOUR_DOMAIN_HERE
    stage: ${self:provider.stage}
    certificateArn: YOUR_CERTIFICATE_ARN_HERE
    endpointType: "edge"
    securityPolicy: tls_1_2
    apiType: rest
    autoDomain: true
    autoDomainWaitFor: 120

(Don’t forget to fill the fields with your own values).

Once it’s done, deploy:

sls deploy --stage staging

After a few minutes, we can access to our app with our own domain !

… Really ?

Try to access to the documentation page located at /docs, you see the trap ?

FastAPI documentation error

This error occurs because of what we did previously to access the documentation page with the lambda default endpoint.

We just need to rollback:

app = FastAPI(title="MyAwesomeApp", openapi_prefix=openapi_prefix) # Change this

app = FastAPI(title="MyAwesomeApp") # With this

Deploy again.

Tada GIF

You now have your application running on AWS Lambda, with your own domain !

Conclusion

Through this article written in the form of a tutorial, you are now capable of creating a FastAPI application, test it locallly and deploy it on the cloud !

If you have any questions, feel free to contact me. Don’t hesitate !

See you soon,

Adem.