--- aliases: up: "[[00_devop_note]]" tags: - devop --- w # What is uWSGI? **uWSGI** is an application server that sits between a web server (like Nginx or Apache) and a Python web application (like Django, Flask, or FastAPI). It runs your Python code and handles incoming web requests. The name comes from **WSGI** (Web Server Gateway Interface), which is the standard Python spec (PEP 3333) that defines how web servers talk to Python applications. The lowercase "u" is the Greek letter μ (micro), suggesting it's lightweight — though in practice it grew into a full-featured server. ## Why do we need it? A plain web server like Nginx doesn't know how to execute Python code. It only serves static files (HTML, CSS, images) and forwards dynamic requests elsewhere. You need a process that: 1. Loads your Python application into memory 2. Receives requests from the web server 3. Calls your Python code with the request 4. Returns the response back to the web server That middle process is uWSGI (or alternatives like Gunicorn). ## The typical stack ``` Browser → Nginx → uWSGI → Python app (Django/Flask) ``` - **Nginx**: handles SSL, static files, load balancing, gzip, caching - **uWSGI**: runs Python workers, manages processes/threads - **Python app**: your business logic Nginx and uWSGI usually talk over a **Unix socket** (fast, local) or a TCP port. The protocol between them is called the **uwsgi protocol** (lowercase) — a binary protocol that's faster than plain HTTP. ## Key features - **Process management**: spawns multiple worker processes to handle concurrent requests - **Threading**: each worker can run multiple threads - **Auto-reload**: restart workers when code changes (dev mode) - **Emperor mode**: one master process supervising many vassal apps - **Cheaper mode**: dynamically scale workers up/down based on load - **Multi-language**: despite the name, also supports Ruby, Perl, Go, etc. ## Minimal config example A typical `uwsgi.ini`: ```ini [uwsgi] module = myproject.wsgi:application master = true processes = 4 threads = 2 socket = /tmp/myproject.sock chmod-socket = 660 vacuum = true die-on-term = true ``` - `module`: entry point (the WSGI callable) - `processes`: how many worker processes to fork - `socket`: where Nginx connects to - `vacuum`: clean up the socket on exit - `die-on-term`: shut down cleanly on SIGTERM ## Running it ```bash uwsgi --ini uwsgi.ini ``` Or in production, run it under **systemd** so it restarts on failure. ## uWSGI vs Gunicorn Both are WSGI servers. The community has largely shifted toward **Gunicorn** because: - Simpler config - Fewer footguns - Easier to deploy uWSGI is more feature-rich and faster in some benchmarks, but its config surface is huge (hundreds of options) and the project has had governance/maintenance concerns. For new projects, Gunicorn behind Nginx is the common default. ## When you'll see uWSGI - Legacy Django/Flask deployments - Setups that need uWSGI-specific features (Emperor, cheaper, etc.) - Docker images for older Python web apps ## Related - [[Apache Tomcat]] — the Java equivalent role (servlet container running Java apps behind a web server)