Files
awesome-python/website/data/category_intros/web-servers.md
T
Vinta ChenandClaude 36880b3d87 docs: rewrite Web Servers category intro lead
This lead followed the same appositive frame as the other category intro leads ("X, a/the Python Y library ..."), so it read as one template with the category swapped in; it now has its own sentence frame, keeping the same picks and facts.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 14:53:13 +08:00

4.1 KiB
Raw Blame History

In production, Gunicorn serves WSGI apps like Django, and Uvicorn ASGI apps like FastAPI. Need a Python web server on Windows? Waitress runs WSGI there.

How to choose:

  • A WSGI app (Flask, Django) on Linux or macOS: Gunicorn
  • An ASGI app (FastAPI, Starlette): Uvicorn
  • A WSGI app on Windows, or a server in pure Python: Waitress
  • One server for both ASGI and WSGI apps, or throughput above all: Granian
  • An app on Trio, or HTTP/3 from the Python server: Hypercorn

Gunicorn is a pre-fork server: one process manages a pool of worker processes. It's built for Unix. With its default sync workers, your proxy must buffer slow clients, or Gunicorn is open to denial-of-service attacks. Start with (2 × CPU cores) + 1 workers and adjust under load. For long blocking calls, streaming, or WebSockets, switch to async workers like gevent.

Uvicorn is an ASGI web server. In production, run it under a process manager. Its built-in one starts workers with --workers and restarts any that die, and its docs also cover running Uvicorn workers under Gunicorn. In a container, run a single Uvicorn process and let your orchestrator scale the number of containers.

Granian is a Rust HTTP server that serves ASGI, WSGI, and RSGI apps from one package. Its README suggests it when you care about throughput above all, and not when you want pure Python or your app relies on Trio or gevent. Pass --interface asgi or --interface wsgi, since the default is RSGI. Start with one worker per CPU core, or one per container on Docker or Kubernetes, rather than numbers suggested for other servers.

Hypercorn is an ASGI server inspired by Gunicorn. It speaks HTTP/1 and HTTP/2, with WebSockets over both, and runs on Trio as well as asyncio. For HTTP/3, install its h3 extra. Its docs recommend setting server_names to the hosts you serve, to block DNS rebinding attacks.

Waitress is a pure-Python WSGI server with no dependencies outside the standard library, and it runs on both Unix and Windows. Waitress doesn't support TLS itself, so put a reverse proxy in front of it for HTTPS.

Put a proxy like Nginx in front: Gunicorn's docs strongly recommend it, and Uvicorn's recommend it for resilience. Behind a proxy, tell your server which proxies to trust for X-Forwarded-* headers, since any client can set them. Uvicorn and Gunicorn take --forwarded-allow-ips, Granian trusted_hosts, Hypercorn ProxyFixMiddleware, and Waitress trusted_proxy. In Uvicorn, Gunicorn, Granian, and Waitress, trust every address with * only when no client can reach the server directly.