Deploying with Python + FastAPI + Postgres

Ali Akram
6 min readDec 28, 2022

--

Introduction

In this post, I’ll talk about the development and design of creating an (API) Application Programming Interface using python. I built a basic API following a series by Sanjeev Thiyagarajan. The API is built using the FastAPI library, one of my favourite frameworks to create API’s in. I’ll go over the main components used in the architecture of this API, as well as some of the reasons I love FastAPI. The API service serves no functional purpose and is instead just a template of how to go about designing an API service.

Architecture Overview

The Architecture is comprised of an API built using the FastAPI framework in python, and Postgres for the Database and is hosted on a Ubuntu Server on Digital Ocean.

Architecture Overview‍

API Systems Design

FastAPI Design

FastAPI is the bread and butter of this API, if you ever worked with Flask or Django its more similar to flask but production-ready out of the box, and dare I say, it's fast, according to the FastAPI folks they say its as fast as GoLang! FastAPI also gives us OpenAPI docs out of the box.

OpenAPI Documentation Generate Automatically by FastAPI

Having an OpenAPI Specification is critical anytime you want to create and maintain a service and easily allows users of your service to understand how to make requests.

Along with the OpenAPI docs, FastAPI has integration with pydantic, a framework that allows use to validate the objects being sent to my API, since python isn’t a typed language adding a layer of validation is critical in the development of an API as it makes my endpoints more robust and offers a way to communicate easily if the right or wrong objects were passed to the endpoints.

Postgres DB + SQLAlchemy

For the Database, I used Postgres as it is a popular open-source SQL database and easily integrates with SQLAlchemy, which in return integrates nicely with fastapi. If you don’t know what SQLAlchemy it's essentially black magic that lets you code your databases tables as objects in python, this is referred to as an Object Relational Mapper (O.R.M.)! So when I start up the application it will automatically be able to create the databases for us without us manually having to do so!

Since I am using SQLAlchemy, I can also leverage the use of alembic; a toolkit for SQLAlchemy, making it easy for developers to specify (in code) the changes they want to make to their database and version these changes. If at any time in the future I wish to revert back to any prior version of the database, alembic will allow us to do so.

database versioned changes

The way alembic accomplishes this is by creating a template script, which I fill out for the change I want to make to the database, and also include in it a method which I fill out to undo the change. This is critical if I make a change by mistake to my database, since my code is versioned and am now coding my database, I should have a way of reverting the changes.

change made to the database

Deployment Practises

Testing with Pytest

Any software isn’t complete until you add tests, for tests I am using the tried and true PyTest library. Thankfully FastAPI has a TestClient I can use when wanting to test the routes of my application. The only tricky part of setting up testing is making sure to create a test database since I still need to run tests with a database that takes entries from my API. To do this I create a file that configures the tests to have ready for us all the fixtures (things I need to be fixed) before I can run test functions.

Fixtures sound complicated but they are not, they are just things needed before running tests, in this case, they are things like a database with data in the database and a client to make requests with. I don’t want to keep on creating these things every time we create a new test which is why I create a file, conftest.py, and put the main fixtures in here.

Deploying with Digital Ocean

One of the major things I learned from this entire process was how to actually host an application on a server and not just in your 127.0.0.1 “home”. I easily set up a Digital Ocean Server with 1 GB of ram and 25 GB of disk space, this process was super duper easy, I’ve never done it ever in my life but was able to do it with no problem right off the bat, I’m also using credits so this is essentially not costing me anything to run!

After I created the server on Digital Ocean, that’s where the real work began. I created a service, managed by systemd, to specify a process I want to run every time the instance is rebooted. That process is my application, so anytime the service goes down and spins back up our server will be able to automatically restart the API service. I also set up an NGINX, server which is used to configure our server to used to create an HTTPS server for our API. The service I created runs gunicorn with uvicorn running my FastAPI application. Gunicorn is a WSGI HTTP server which is a communication protocol that helps our application communicate with requests being sent to my webserver. and Uvicorn allows us

CI/CD with GitHub Actions

Now that I created an API with a database, added tests, and hosted it on a server. It was time to automate the steps required after making changes to my code, mainly being the testing and deployment of the code. This is known and Continuous Integration and Continuous Delivery, CI/CD. CI/CD not only ensures that you are delivering code that works but it is a way of eliminating the repetitive tasks which occur between pushing changes to your code and having those changes appear on your final application.

‍‍

You can take a look at the code on my here. For the course I followed you can take a look at Sanjeevs Channel on YouTube here.

Get $200 for free on Digital Ocean :), this instance cost me 6$ a month so you can basically host something similar for about 2 years for free :O!

--

--

Ali Akram

I'm a Machine Learning Engineer, and part-time deep thinker :)