How to Deploy your FastAPI Backend with PostgreSQL Database to Render
Tags: fastapi, python, render, hosting
Published: 2024-06-19 13:54:16

## Introduction
[FastAPI](https://fastapi.tiangolo.com/) is a popular Python backend web development framework. Many Python developers use FastAPI to built Application Programming Interfaces (APIs) and connect other backend infrastructure such as databases. FastAPI is suitable for API design for several reasons:
* APIs built using FastAPI are fast in terms of performance.
* FastAPI framework is simple to learn.
* FastAPI comes with a built-in API documentation feature that saves the developer the time needed to manually document APIs.
* FastAPI is generally optimized for API design.

This tutorial walks Python developers through the process of hosting APIs built using FastAPI to the [Render cloud hosting service](https://dashboard.render.com/), and connecting a PostgreSQL database. The article assumes you have your FastAPI backend ready for deployment. However, I will walk you through the deployment checks involved to get your code ready, so you can apply the checks you might have missed. Let's go!

## Prerequisites
1. A FastAPI backend
2. A registered [Render account](https://dashboard.render.com/register)

## Pre-Deployment
### Deployment Checks
Assuming you have written the logic for all your APIs and have tested that everything is working as expected, there are five steps extra steps we are going to take to ascertain that our backend is ready for production:

#### 1. Create a requirements.txt file

You obviously installed software packages to build your APIs inside your Python virtual environment. Among the packages is the FastAPI framework itself and all its dependencies. We will need to install the same packages to run our code in production. We need to pass to the Render build process a list of dependencies for our project.

In your local environment, create a file named **requirements.txt**. You could name it anything, but naming it as above is a standard convention. Next, run `pip freeze > requirements.txt` in your terminal. The command gathers the names of all the software dependencies and their version numbers from your virtual environment, and outputs the information in the requirements.txt file

#### 2. Create a .env file

Next you need to hide any sensitive information in your codebase before you push your code to Github. In most cases, the sensitive information in most Python projects is your project's secret keys, database URL connection string, and database name, username and password. You could include database port and host if you deem them sensitive enough to be hidden.

Proceed to create a hidden file called `.env`. Do not forget the period at the beginning. Edit the file by providing key-value pairs of the secret information like this:
```
DATABASE_PORT=5432
DATABASE_NAME=fastapi
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=testpass123
SECRET_KEY=123456HDUDCDHCHDUCDNCNDNCR
```
Remember to replace the environment variables values with your actual values.

#### 3. Create a .gitignore file

This steps precedes pushing your code to Github and it involves instructing git to ignore directories and files you do not want checked into Github. By default, when you initialize a git repository as we will do in a moment, git tracks all files in the entire directory. We do not want version control to track the .env file. In addition, we do not want to check our virtual environment folder or the __pycache__ directory into Github. This is because we can easily recreate our virtual environment. Furthermore, we do not want to pollute our Github repository with code we do not need, such as __pycache__ files and virtual environment packages.

Untrack unnecessary files by editing the .gitignore file like this:
```python
__pycache__/
venv/ # Use your virtual environment's name
.env
```

#### 4. Create a build.sh file

This step involves creating a bash file called `build.sh` that will store our pre-deploy commands. We will run this file shortly when we host our code on Render.

Let's talk about pre-deploy commands. These are commands that should run before you start your production server. Most often, these are commands that set up your production database. They may involve commands that set up your database schema and tables and run database migrations. Additionally, you can run pre-deploy commands to upload your static files to a Content Delivery Network (CDN).

In most cases, with FastAPI and other Python frameworks such as Django, pre-deploy commands involve running database migrations to create schema and tables. Django, in particular, auto-generates migration files every time you make changes to your database. Therefore, with Django, you almost always have to write only these two database migration commands in your build.sh file:
```python
python manage.py makemigrations
python manage.py migrate
```
However, FastAPI does not create any migration files when you make changes to your database. For a serious project, you usually have
to integrate a database migration tool like [Alembic](https://testdriven.io/blog/fastapi-sqlmodel/), which tracks changes to your database schema. If you integrated Alembic into your FastAPI backend, first write this database migration command in build.sh to set up your schema:
```
alembic upgrade head
```
However if you did not integrate any database migration tool, you typically wouldn't have to run pre-deploy commands on Render. 
Assuming you do not need to make database migrations for your FastAPI, our build.sh file will contain only one command; the command to start our production server. Input the following command in your build.sh file:
```shell
uvicorn main:app --host 0.0.0.0 --port $PORT
```
**Note**

FastAPI ships with the [uvicorn](https://fastapi.tiangolo.com/deployment/manually/) server by default. The above command presumes that the entry point to your backend, the main.py file, is located at the root directory of your project. If the file were located in some sub-directory, you would have to provide the relative path to the file, i.e relative path to the root directory

Also, take note of the host IP. The IP is set to the 0.0.0.0 address, which is a special network interface that accepts connections from all IPs. The port option specifies an environment variable **PORT**. Using an environment variable instead of hard-coding a specific port number is considered best practice. The hosting service build process will assign us a random port during the build. You could hard-code a port, say 5000 or 10000 and hope the port is not occupied by another process during the build. 

#### 5. Initialize a Github repository and push your code to Github

Go to your Github account, create a new public repository and copy the repository's URL. Back in your command line, enter these prompts, in order,
at the root of your project folder
```python
git init # Initializes a local git repository
git add --all
git commit -m 'FastAPI backend' # Commit message could be anything you want
git branch -M main # Sets up a branch called 'main' on Github
git remote add origin [Your repository URL] # Sets up a remote repository on Github
git push origin main # Pushes all your code to the main branch of your Github repository.
```

All your code is now hosted on Github

## Deployment
### Set up a PostgreSQL Database on Render
Follow these steps to spin up a free PostgreSQL database on Render:
1. Login into your Render account. You will be redirected to your dashboard.
2. Click on **new** and select **PostgreSQL** from the dropdown menu.
3. Fill in the Database, Name and User fields with the database credentials you want to use.
4. Scroll down to **Instance Type** and select free instance. You can select a paid instance for an enterprise-level project.
5. Hit **Create Database** at the bottom of the page and wait for Render to create a new PostgreSQL database instance for you. Render will redirect you to a page with information about the newly created database.
6. Copy the generated **Database Password** and **Database Internal URL** somewhere.
Note that we are using [Internal URL](https://docs.render.com/databases) and not external URL because both our  service and database are hosted within the same server. Connecting using the internal URL speeds up the connection process and reduces latency.

### Create a Web Service
1. Click on new again, and select **Web Service** from the dropdown.
2. Choose **Build and deploy from a Git repository** and press **next**. Render will connect to your Github and avail all your public repositories. Connect your FastAPI repository.
3. Fill in details about your web service in the resulting page:
  1. Input a suitable unique name for your service under **Name** field
  2. Scroll down to **Runtime** field and select **Python3** from the dropdown
  3. Input `pip install -r requirements.txt` command under  **Build Command**
4. Run your build.sh file under **Start Command** field like this:
    ```shell
    ./build.sh
    ```
    You could just input the command required to start our production server directly into the Start Command field since we do not have any other pre-deploy command. However, in a future event where you would need to run database migration commands, it is best practice to create a build.sh file to run all your commands at once.

5. Select the instance type of your choice. If it is a practice project, select the **free instance** type.
6. Add environment variables
  You can proceed in either of the following ways in Render:
  1. You can add your environment variables one-by-one from your `.env` file by clicking on the **Add Environment Variable** button.<br>

  2. You can also click on **Add from .env** which will provide an input field. Proceed to copy the contents of your .env file from your local machine and paste them in the input field provided, then click on **Add variables**.

    Remember that we added the details of our new PostgreSQL instance, which are different from the database you were using locally. Return to the dashboard and you should see the PostgreSQL instance you just created, marked as **available**. Click on it and note the database name, database user, database password and database **internal** URL details. Then proceed in either of the two ways discussed above to set your environment variables on Render.
7. Click on **Create Web Service** to initialize the build process. The process will take a few minutes after which your new web service URL will be generated. You can visit your service on the browser by clicking on its URL. If the build process fails for some reason, Render will inform you. You should review the build logs to fix any errors.

## Conclusion
Hosting your FastAPI backend with a PostgreSQL database on Render is a fairly simple process. First you will need to prepare your project for production by creating a requirements.txt file, a .env file, a .gitignore file and a build.sh file. Then you will need to push all your code to Github. Finally, you need to proceed to your Render account and create a PostgreSQL database instance, then create your web service by passing in a build command, a start command and your environment variables. Hope this helps. Happy hosting!