Deploy a Python FastAPI Application to Render

daneasterman

Daniel Easterman

Posted on July 10, 2024

Deploy a Python FastAPI Application to Render

In the world of Python frameworks, FastAPI is the new kid on the block and a great choice for building APIs. Equally, Render is a good option for developers who want to quickly test their applications in a production environment for free.

In this post, we'll run through how to deploy a FastAPI app to Render. First, though, let's explore why FastAPI and Render are often chosen by developers.

Why FastAPI?

FastAPI is a high-performance microframework used primarily for building APIs (the clue is in the name). As such, FastAPI offers several advantages over older, better-known frameworks such as Django and Flask.

The first and most obvious advantage of FastAPI is that it was built with scalability and performance in mind.

For example, FastAPI is based on an asynchronous ASGI server rather than the older WSGI used by Django and other frameworks. ASGI servers can handle multiple requests simultaneously (concurrently). This is often seen as a better option for apps that need to handle high levels of user traffic.

FastAPI also makes it easier for developers to write asynchronous code by simply using the async keyword when defining asynchronous functions.

But FastAPI's shiny "newness" is also its main drawback. Because it was only introduced in 2018, FastAPI has a much smaller community and fewer learning resources (such as coding tutorials) compared to the more established frameworks. This is something to bear in mind when choosing FastAPI for your next project.

Why Render?

Render is a great option for developers who want to quickly test their applications in a production environment for free.

With Render, you don't even have to enter your credit card details to gain access to the free tier. So unlike other cloud services, there is no way to rack up charges by mistake.

As we will see in the section below, Render also provides an excellent overall developer experience with a clean, very easy-to-use UI and smooth integration with Git and GitHub. An added bonus is that any app you host on Render gets a free TLS certificate right out of the box.

The downside with Render's free tier is that it can take a long time for deployments to complete. Once this starts to become an issue, you might want to consider upgrading to one of the paid plans.

Create a FastAPI Demo Application

You can view, download, or clone the full code used in this article.

The first thing we need to do is create an empty directory where our project will live. Let's call it fastapi-render-appsignal.

Run the following commands in your terminal:

mkdir fastapi-render-appsignal
cd flask-heroku-appsignal
touch main.py
Enter fullscreen mode Exit fullscreen mode

The entry point for the project will be main.py.

Next, we need to make our project a git repository by running the git initialize command in the root of the directory:

git init
Enter fullscreen mode Exit fullscreen mode

Also, create a requirements.txt file in the project's root directory. Add these two lines to the file:

fastapi
uvicorn[standard]
Enter fullscreen mode Exit fullscreen mode

Then run:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

If the installation goes smoothly, you should see the following output in the terminal:

Installing collected packages: websockets, uvloop, typing-extensions, sniffio, pyyaml, python-dotenv, idna, httptools, h11, exceptiongroup, click, annotated-types, uvicorn, pydantic-core, anyio, watchfiles, starlette, pydantic, fastapi
Successfully installed annotated-types-0.6.0 anyio-4.2.0 click-8.1.7 exceptiongroup-1.2.0 fastapi-0.109.0 h11-0.14.0 httptools-0.6.1 idna-3.6 pydantic-2.5.3 pydantic-core-2.14.6 python-dotenv-1.0.1 pyyaml-6.0.1 sniffio-1.3.0 starlette-0.35.1 typing-extensions-4.9.0 uvicorn-0.27.0 uvloop-0.19.0 watchfiles-0.21.0 websockets-12.0
Enter fullscreen mode Exit fullscreen mode

Now, in main.py, copy and paste the following barebones boilerplate code:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}
Enter fullscreen mode Exit fullscreen mode

Let's go line-by-line and explain what is being done in this short code snippet.

  1. After the import statements, we create an instance of the FastAPI class and assign it to the variable app.
  2. @app.get("/") is a Python decorator that tells FastAPI to create an API endpoint via the HTTP GET method at the root URL /.
  3. async def root() defines an asynchronous function named root. We are using the async keyword here because FastAPI is built to work with asynchronous I/O operations. This means it can handle concurrent requests, which is better for performance.
  4. In the body of the function, we return a Python dictionary which FastAPI helpfully converts to JSON for us. So, when the user goes to the root / endpoint, our API will automatically respond with a JSON object.

We can now run our project using the server package Uvicorn (that we installed earlier) with the following command:

uvicorn main:app --reload
Enter fullscreen mode Exit fullscreen mode

If we open our browser at http://127.0.0.1:8000, we will just see the following plain JSON response:

{ "message": "Hello World" }
Enter fullscreen mode Exit fullscreen mode

But if we add /docs to the end of the URL, we can take advantage of FastAPI's in-built interactive API documentation capabilities.

The documentation UI in the screenshot below is provided by Swagger UI:

FastAPI Swagger UI API documentation screen

You can also try another documentation UI style that's automatically included with FastAPI.

Enter the URL http://127.0.0.1:8000/redoc in your browser.

This one is provided by ReDoc:

FastAPI ReDoc API documentation screen

Deploy on Render

This part assumes you have already created a repository for this project on GitHub. If you need instructions on how to do this, check out GitHub’s official docs.

One of Render’s advantages is that it provides an easy and intuitive way to connect to your GitHub repository.

First, go to render.com and create a new account with Render (you can use your GitHub credentials to speed things up).

Then click on the New button and select the option to create a new web service.

After linking your GitHub account, you should see the screen below, which provides a list of GitHub repos to connect to Render. Let's select our fastapi-render-appsignal example project.

List of GitHub repos in Render

This will then take us to the main configuration screen. Under region, simply select the region closest to your location (since I’m based in the UK, I will choose Frankfurt):

Render config screen with region option

Further down the screen, we have a few more important options.

The build command will use the requirements.txt file we created earlier in the project to install all the packages from our project on Render’s remote server.

Under start command, we will use Uvicorn again in our production environment and tell Render to start the application using main.py in the root of our project.

Note: You must explicitly tell Render which host and port to use (unlike when using other servers like gunicorn). Unfortunately, this is not mentioned in any of the official Render documentation but I found the solution in the Render community forum and in the post 'Deploying FastAPI application to Render'.

Render config screen with start and build command settings

Next, choose the free option under the list of instance types:

Render instance types with pricing options

Lastly, under environment variables, specify the Python version as 3.10.7. Ensure this matches the same version you are using in your local project.

With our web service configuration done, now we simply click the Create Web Service button and watch the project get deployed:

Render screen showing web service deployment process log

Remember, this will take a bit of time since we are using the free plan.

If everything goes smoothly at the end of the deployment process, we should see a final message in Render's logs saying: "Your service is live".

Render screen showing service is live in logs

Now we can click on the public link Render has generated for us and see our Hello World FastAPI example, including the automatic documentation links at /docs and /redoc:

Screen showing service deployed at Render URL

Installing the AppSignal Dashboard for FastAPI and Monitoring Deploys

It's great that we now have a basic FastAPI app running and deployed to Render, but what if something goes wrong? Even with the best manual and automated testing, the reality is that errors and bugs happen in software development. The key thing is to get alerted as soon as errors happen and to quickly identify where the problem is in the code.

In this section of the tutorial, we are going to specifically look at how to enable AppSignal to monitor your deployments. This part of the setup is crucial for you to see which errors are associated with a specific deployment. This will allow you to diagnose and fix problems in your app quickly and efficiently.

First, sign up for an AppSignal account (you can do a 30-day free trial, no credit card details required).
Next, add appsignal and opentelemetry-instrumentation-fastapi to your requirements.txt file:

# requirements.txt
appsignal
opentelemetry-instrumentation-fastapi
Enter fullscreen mode Exit fullscreen mode

Then run:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Now we need to create an appsignal.py configuration file and add the following code:

import os
import subprocess
from appsignal import Appsignal
from dotenv import load_dotenv
load_dotenv()

revision = None
try:
    revision = subprocess.check_output(
        "git log --pretty=format:'%h' -n 1", shell=True
    ).strip()
except subprocess.CalledProcessError:
  pass


appsignal = Appsignal(
    active=True,
    name="fastapi-render-appsignal",
    push_api_key=os.getenv("APPSIGNAL_API_KEY"),
    revision=revision,
)
Enter fullscreen mode Exit fullscreen mode

In the code above, we initialize the Appsignal object with a few different parameters, including:

  • Setting active to True to enable monitoring.
  • Providing the name for our application.
  • Putting the API key in an environment variable.

But the key parameter to enable deploy tracking is the revision parameter. Inside the try-except block (above the AppSignal initialization code), we fetch the latest commit hash so AppSignal can keep track of our deploys.

Lastly, we need to update main.py to finish setting up AppSignal in our FastAPI app:

# main.py
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor #new
import appsignal #new

appsignal.start() #new

app = FastAPI()

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

@app.get("/items/{item_id}")
async def get_item(item_id: int):
    return {"item_id": item_id}

FastAPIInstrumentor().instrument_app(app) #new
Enter fullscreen mode Exit fullscreen mode

When we check out our AppSignal dashboard, the first thing we will see is the Getting Started screen which will provide some suggestions on additional configuration steps to complete:

Getting started screen in AppSignal dashboard

But here we'll just focus on ensuring that AppSignal can track our deploys.

Go to the Organization page in the AppSignal dashboard and then click on Organization settings to activate AppSignal's integration with GitHub. Check out AppSignal's official docs on linking your repo for step-by-step instructions.

With the GitHub integration set up and your repo linked, all you need to do now is trigger a deployment in Render for AppSignal to start monitoring your deploys.

In our case, we simply need to push to our main branch:

git push origin main
Enter fullscreen mode Exit fullscreen mode

If everything is set up correctly, we should see AppSignal tracking our deploys and any errors associated with each deploy commit hash in the Deploys section of the dashboard:

Deploys screen in AppSignal dashboard

And that's it!

Wrapping Up

In this guide, we covered a lot of ground! First, we briefly introduced some of the advantages and disadvantages of choosing FastAPI and Render.

Then, we created a simple FastAPI app, deployed it to Render, and ended by monitoring those deploys with AppSignal.

Happy coding!

P.S. If you'd like to read Python posts as soon as they get off the press, subscribe to our Python Wizardry newsletter and never miss a single post!

💖 💪 🙅 🚩
daneasterman
Daniel Easterman

Posted on July 10, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related