Beginners are always obscured about why Flask needs Nginx and WSGI server and how much performance they increase. I used Flask for small projects that do not care much about production, so whether to use these frameworks was not a big problem for me. Recently, I’ve been working on some projects that required serious attention on them. After doing some research, I thought It was great to note it down.

Web Server VS Web Application

First thing first, let’s get started by explaining what each one of them is.

Nginx is a web server, which means it interacts with clients through HTTP/s protocol.

Flask is a web application.

I shall shed more light on them.

A web application and a web server are almost the same, except that a web server is a “server” that focuses on serving contents, while a web application cares more about the business logic.

You see, Nginx can serve static files like HTML under specific directories and act as a proxy agent redirecting requests to some other web server or applications. This kind of proxy is also called the reverse proxy. However, it couldn’t care more about the business logic.

Web server is also optimized to serve clients. For example, caching the static contents to reduce the hit to the servers/applications behind it; Another example, it uses an asynchronous, event-driven approach to handle connections from the client side so that thousands of millions of requests can be handled in a non-blocking manner 1.

Unlike web servers, web applications care about the content and might not focus too much on delivering it. It usually follows the MVC software architecture, in which the M stands for model that reflects the business logic. Taking Twitter as an example, it knows the user and the tweets posted by this user, the followers, the followings of whom, etc. So, when a user sends an HTTP request for updating the timeline, it should end up responding with content for that user, not someone else. That’s why I said web application cares more about the business logic.

WSGI

Now, you must wonder how web server “talks” to web applications. At first, I thought it was simple as redirecting HTTP requests, it turns out that a more common way is through WSGI. By the time web development was booming, many Python web applications had implemented the interface for web servers differently. It limits the choices of web servers if an application is chosen, or vice versa 2. Hence a proposal was submitted for resolving the problem, which is WSGI.

Flask behind Nginx

During the development, Flask provides a simple web server Werkzeug for that purpose. Start a flask app, and send a request with curl -v , you should see the content denoting the server.

$ curl -v localhost:8000/
*   Trying 127.0.0.1:8000...
....
< Server: Werkzeug/2.2.2 Python/3.10.3
...

Werkzeug is not meant for production by its nature. So when we deploy, we need a more reliable web server. Nginx is one of the common options. When deploying the Flask app with Nginx, the performance does not increase from Flask’s perspective, but because Nginx provides features like caching, it makes the Flask app more durable.

Using Nginx directly to deploy Flask is not the best option because Nginx doesn’t support WSGI, and Flask is essentially a WSGI app, meaning it needs a Web Server that supports it. And Gevent can be used as a web server that supports WSGI!

Then, why not just use Gevent + Flask? Well, according to the documentation of Flask.

Gevent should not be run as root because it would cause your application code to run as root, which is not secure.

If your application doesn’t use port 80 or 443, which are common ports for HTTP and HTTPS, then the Gevent-Flask combo is enough. However, if you need those default ports for your application ( actually, any well-known ports, from 1 to 10233), you should consider using a more secure web server.

With that being said, let me conclude my study.

  1. Flask uses Werkzeug as a development server.
  2. Werkzeug is not desiged for production.
  3. If you care about using the well-known ports, you should use the Web Server + WSGI Server + Flask combo.
  4. If you do not care about using the well-known ports, WSGI Server + Flask is enough.

References