WSGI Concepts
When you run a Flask app, there’s always a “server” involved.
But your Flask code is just Python functions. So how does an HTTP request become a Python function call?
That bridge is WSGI.
What is WSGI?
WSGI stands for Web Server Gateway Interface.
It’s a Python standard that defines a simple contract between:
- a WSGI server (Gunicorn, uWSGI, Waitress)
- a WSGI app (Flask app)
The goal: any WSGI server can run any WSGI-compatible Python web app.
The simplest WSGI mental model
A WSGI server:
- Accepts an HTTP request from the network
- Builds an
environenvirondictionary (details about the request) - Calls your Flask app like a Python callable
- Receives the response body iterator
- Sends bytes back to the client
false
flowchart LR C[Client] -->|HTTP| WS[WSGI Server] WS -->|environ + start_response| F[Flask (WSGI App)] F -->|status, headers, body| WS WS -->|HTTP Response| C
false
Dev server vs WSGI server
When you run:
flask runflask run
Flask uses a development server (Werkzeug).
It is:
- fine for local development
- not designed for heavy production workloads
- not tuned for security/hardening
In production, you typically run Flask behind:
- Gunicorn (WSGI server) and often
- Nginx (reverse proxy for TLS, caching, static files, etc.)
Where does “WSGI app” live in Flask?
If you have:
from flask import Flask
app = Flask(__name__)from flask import Flask
app = Flask(__name__)appapp is a WSGI application callable.
WSGI servers point to it like:
gunicorn "app:app"gunicorn "app:app"
Meaning: import the module app.pyapp.py, then use the appapp variable.
Why you should care
Understanding WSGI helps you debug:
- “It works locally but not in production.”
- incorrect host/port binding
- reverse proxy headers (X-Forwarded-For)
- timeouts and worker model issues
If this helped you, consider buying me a coffee ☕
Buy me a coffeeWas this page helpful?
Let us know how we did
