Gunicorn
It tends to integrate easily with hosting platforms.
It is easy to install as it does not require additional dependencies or compilation.
It has built-in async worker support using gevent or eventlet.
This page outlines the basics of running Gunicorn. Be sure to read its documentation and use to understand what features are available.
Create a virtualenv, install your application, then install gunicorn
.
The only required argument to Gunicorn tells it how to load your Flask application. The syntax is {module_import}:{app_variable}
. module_import
is the dotted import name to the module with your application. is the variable with the application. It can also be a function call (with any arguments) if you’re using the app factory pattern.
The -w
option specifies the number of processes to run; a starting value could be CPU * 2
. The default is only 1 worker, which is probably not what you want for the default worker type.
Logs for each request aren’t shown by default, only worker info and errors are shown. To show access logs on stdout, use the --access-logfile=-
option.
Gunicorn should not be run as root because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as or Apache httpd should be used in front of Gunicorn.
0.0.0.0
is not a valid address to navigate to, you’d use a specific IP address in your browser.
The default sync worker is appropriate for many use cases. If you need asynchronous support, Gunicorn provides workers using either or eventlet. This is not the same as Python’s async/await
, or the ASGI server spec. You must actually use gevent/eventlet in your own code to see any benefit to using the workers.
When using either gevent or eventlet, greenlet>=1.0 is required, otherwise context locals such as request
will not work as expected. When using PyPy, PyPy>=7.3.7 is required.
To use gevent:
To use eventlet: