How to Publish Your First Python App on Heroku

Casper Henson
5 min readSep 8, 2020

Heroku is one of the most popular Platforms as a Service (PaaS) which allows developers to develop and deploy their applications to the cloud.

So, let’s get started. We will quickly sign up for an account on the Heroku homepage.

Heroku has a Heroku CLI to interact with its services which can be installed on MacOS, Linux and Windows.

For Mac, use brew install heroku

For Windows, Download the installer from here.

For linux, use sudo snap install — classic heroku

Once the Heroku CLI is installed, make sure to sign in into the CLI using “heroku login”.

To start a Python application, we need to first set up the Python virtual environment using:

pip install virtualenv

Once virtualenv is installed, we can create a virtual environment, with a path to python 3 binary, for example:

➜  ~ virtualenv -p /usr/local/Cellar/python\@3.8/3.8.2/bin/python3 ~/python33
created virtual environment CPython3.8.2.final.0-64 in 3309ms
creator CPython3Posix(dest=/Users/m0a04y6/python33, clear=False, global=False)
seeder FromAppData(download=False, pip=bundle, wheel=bundle, setuptools=bundle, via=copy, app_data_dir=/Users/m0a04y6/Library/Application Support/virtualenv)
added seed packages: pip==20.1.1, setuptools==47.3.1, wheel==0.34.2
activators PythonActivator,FishActivator,XonshActivator,CShellActivator,PowerShellActivator,BashActivator

Once the virtual environment is created, it can be activated using:

~ source ~/python33/bin/activate

We will now install the flask and gunicorn dependencies, which are required to create our Python application.

(python33) ➜  ~ pip install flask
Collecting flask
Using cached Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous>=0.24
Using cached itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1
Using cached Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting click>=5.1
Using cached click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Werkzeug>=0.15
Using cached Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting MarkupSafe>=0.23
Using cached MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl (16 kB)
Installing collected packages: itsdangerous, MarkupSafe, Jinja2, click, Werkzeug, flask
Successfully installed Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 itsdangerous-1.1.0
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the '/Users/m0a04y6/python33/bin/python -m pip install --upgrade pip' command.
(python33) ➜ ~ pip install gunicorn
Collecting gunicorn
Using cached gunicorn-20.0.4-py2.py3-none-any.whl (77 kB)
Requirement already satisfied: setuptools>=3.0 in ./python33/lib/python3.8/site-packages (from gunicorn) (47.3.1)
Installing collected packages: gunicorn
Successfully installed gunicorn-20.0.4
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the '/Users/m0a04y6/python33/bin/python -m pip install --upgrade pip' command.
(python33) ➜ ~

Now that our Python setup is completed and we are ready to create a simple Python Flask API and publish it on Heroku.

First, let’s create a simple app.py which defines a route and the content to be returned when that route is accessed.

RAW

We’ll create wsgi.py, which will be the entry point of our application.

RAW

Create the file requirements.txt as follows:

pip freeze > requirements.txt

And a file called Procfile with contents:

web: gunicorn app.app:app

Now, we are ready to publish this on Heroku. We’ll use the Heroku CLI to create the application and publish the source code to the application.

Create the Heroku application — heroku create our-first-python-app (Note that this name must be unique).

Publish the application — git push heroku master

RAW

This application can now be accessed here.

Congrats!! We have our first Python application running on Heroku cloud.

Scaling the Heroku Application

The application which we just developed is fine for a very low traffic application. However, in the real world, there will be multiple users accessing the application and hence the application should be able to handle the load which all these users would generate.

This is where Heroku allows you to seamlessly scale your application using a simple command such as:

heroku ps:scale web=5

Running this command will ensure that Heroku will run five instances of the application resulting in extra requests to be distributed uniformly over these multiple instances.

However, the question arises how many instances do you need at a particular time? To answer this question, we need to estimate how many requests a single instance can handle.

For this, we need to perform load testing. Load testing is an activity where we send a large amount of requests to an application and estimate at what number of requests / sec does the application’s performance start to degrade.

One of the tools to perform such load testing that I have used in the past is Loadmill.

With Loadmill, I can quickly create a load test to perform the real world load testing simulating traffic from various locations and across devices as shown below:

I can define the duration of the test, concurrency (no. of users), geography and various other parameters to run the load test.

The results of the test will give us a fair idea if the application needs additional scaling depending on our current number of users and the estimated growth.

And there you have it, a quick guide to deploying your first Python app on Heroku.

--

--