Difference between Gunicorn and Nginx
Nginx is a web server and reverse-proxy responsible for serving static content, gzip compression, ssl, proxy_buffers and other HTTP stuff while gunicorn is a Python HTTP server that interfaces with both nginx and your actual python web-app code to serve dynamic content.
Here's a high-level overview of the lifecycle of an HTTP request highlighting their roles. I assume that you have one server running a simple app with three main processes.
Nginx: Listens on port 80 for incoming HTTP requests from the internet.
Gunicorn: Listens on another port(8000 is the popular one) for HTTP requests from Nginx. Gunicorn is configured with your python web app.
Per Gunicorn's deploy doc, my understanding is that you use Nginx as a proxy server for Gunicorn.
As Gunicorn is ported from Ruby's Unicorn, I'm assuming the limitations and specifications of Unicorn apply to Gunicorn as well:
Unicorn is an HTTP server for Rack applications designed to only serve fast clients on low-latency, high-bandwidth connections and take advantage of features in Unix/Unix-like kernels. Slow clients should only be served by placing a reverse proxy capable of fully buffering both the request and response in between Unicorn and slow clients.
Gunicorn's deploy doc says much the same thing:
Although there are many HTTP proxies available, we strongly advise that you use Nginx. If you choose another proxy server you need to make sure that it buffers slow clients when you use default Gunicorn workers. Without this buffering, Gunicorn will be easily susceptible to denial-of-service attacks.
So Gunicorn serves fast, low-latency high-bandwidth clients and Nginx serves the rest.