Python WSGI on Windows: Waitress behind IIS or Nginx
Run a WSGI app with Waitress in a venv, supervise it as a service, and reverse-proxy it without pretending Gunicorn works on Windows.
- Build
- 26100.33650
- Edition
- Standard / Datacenter
- Architecture
- x64
- Support
- Documentation (E1)
- Evidence
- E1Official documentation
- Verified
- 2026-10-29
- Page type
- Task
The short answer
Section titled “The short answer”On Windows, use Waitress as the WSGI server:
C:\apps\api-a\.venv\Scripts\python.exe -m pip install waitressC:\apps\api-a\.venv\Scripts\python.exe -m waitress --listen=127.0.0.1:8000 app:appThen put IIS (HttpPlatformHandler/ARR) or Nginx in front. Gunicorn is Unix-only; do not copy a Gunicorn command to Windows.
Why Waitress
Section titled “Why Waitress”- pure-Python, works on Windows;
- multi-threaded, no fork;
- WSGI-compatible (Flask/Django);
- simple
--listenand thread count.
It is not a process manager. Use a service wrapper (NSSM/WinSW) to keep it running.
Service wrapper
Section titled “Service wrapper”nssm install api-a "C:\apps\api-a\.venv\Scripts\python.exe" "-m waitress --listen=127.0.0.1:8000 app:app"nssm set api-a AppDirectory "C:\apps\api-a"nssm set api-a AppEnvironmentExtra APP_ENV=productionnssm set api-a AppStdout "C:\logs\api-a\out.log"nssm set api-a AppStderr "C:\logs\api-a\err.log"nssm start api-aPin the venv python, not python from PATH. Set AppDirectory so relative templates/config resolve.
IIS in front
Section titled “IIS in front”Two options:
- HttpPlatformHandler launches the Python process; IIS manages lifecycle (see HPH page).
- ARR reverse-proxies to
127.0.0.1:8000; the Python process runs as a service.
Do not do both on the same port. Pick one supervisor.
Nginx in front
Section titled “Nginx in front”location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;}The app must trust the proxy headers; otherwise redirects/absolute URLs use the internal host.
Verify
Section titled “Verify”C:\apps\api-a\.venv\Scripts\python.exe -c "import sys; print(sys.executable)"curl.exe -I http://127.0.0.1:8000/Get-CimInstance Win32_Process -Filter "Name='python.exe'" | Select-Object ProcessId, ExecutablePath, CommandLineCheck sys.executable is the venv, and only one process listens on 8000.
Threads and timeouts
Section titled “Threads and timeouts”Start with --threads=4 to 8 for a small app; measure before raising. Set the front proxy’s read timeout above the slowest legitimate request. A long report should be async, not a 30-minute HTTP request.
Lab boundary
Section titled “Lab boundary”E1. The lab did not install Waitress or run a WSGI app; the commands are the Windows deployment pattern to validate on Server 2025.