Solutions for Serving Python Flask Web Application

A former related article for this topic is Solutions for Serving Python Web Application published in August, 2016.

Flask is a BSD licensed micro-framework for Python based on Werkzeug, Jinja 2 and good intentions. Flask’s built-in server is not suitable for production as it doesn’t scale well. Flask application object is the actual WSGI application. Flask WSGI application is recommended to be called with a production web server

Development Web Server

from flask import Flask
app = Flask(__name__)

def hello():
    return "Hello World!"

if __name__ == '__main__': ## for development, without automatic reloading
## execution
export FLASK_ENV=development 
## introduced in Flask v1.0, use `export FLASK_DEBUG=1` instead for older versions

export FLASK_APP=src/hello:app
flask run 
## `--no-reload` option is possible
## if `FLASK_APP` is not set, application instance or factory in `` or `` would be detected first

Production Web Server - Gunicorn

Gunicorn 'Green Unicorn' is a WSGI HTTP Server for UNIX.

pip install gunicorn
gunicorn -w 4 -b app:app

Production Web Server - Gevent

Gevent is a coroutine-based Python networking library that uses greenlet to provide a high-level synchronous API on top of libev event loop.

pip install gevent

Comparing to other WSGI server which works with Python Flask, Gevent is implemented in Python, which makes it possibly to imports the application as a module and then serves the application just like in Node.js.

from gevent.pywsgi import WSGIServer
from app import app

http_server = WSGIServer(('', 5000), app)

[Optional] Process Manager Integration - Supervisor

Supervisor with Gunicorn and Nginx for Flask Illustration, image from Deploy flask app with nginx using gunicorn and supervisor.

Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems. It shares some of the same goals of programs like launchd, daemontools, and runit.

pip install supervisor

Since this Flask is in Python tech stack, Python implemented process manager Supervisor could be a good option.

echo_supervisord_conf > /etc/supervisord.conf
## add a config file in `/etc/supervisor/conf.d/`
## example configuration can be as follows
supervisorctl start

supervisorctl stop all
supervisorctl status all

supervisorctl reread
supervisorctl update
supervisorctl start example_app

Preposition Server - Nginx

Nginx is a web server which can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache.

NGINX Architecture, from The Architecture of Open Source Applications, Volume II

Besides memcache related part, Nginx can either be used as Proxy Server to communicate with later Web Server which serves Python Flask Application through HTTP or be used as Web Server to communicate with Python Flask Application through FastCGI (which by the way need to be configured or implemented).

Personal Adoption

My initial selection is Nginx as Proxy Server + Gunicorn as Web Server. After I expanded my tech stack to Node.js, I finally adopts the combination that Nginx as Proxy Server + Gevent as Web Server.

And for Process Management, since PM2 also supports Python process and is much better in the aspect of user interface. I adopted PM2 as my process manager.

  ".sh": "bash",
  ".py": "python",
  ".rb": "ruby",
  ".coffee" : "coffee",
  ".php": "php",
  ".pl" : "perl",
  ".js" : "node"
pm2 start --interpreter=/path/to/venv/bin/python


* cached version, generated at 2019-06-21 23:17:41 UTC.

Subscribe by RSS