Skip to content

Deployment#

WSGI: gunicorn or waitress#

hayavega launch's wsgiref dev server is explicitly single-threaded and dev-only — never put it behind real traffic. Every scaffolded project ships config/wsgi.py, a standard WSGI application object:

# Linux/macOS
gunicorn config.wsgi:application --workers 5 --bind 0.0.0.0:8000

# Any platform, including Windows (gunicorn imports fcntl, POSIX-only)
waitress-serve --port=8000 --threads=16 config.wsgi:application

create_application()'s return value is a plain WSGI callable, verified directly against a real multi-threaded server as part of this project's own benchmark suite — not assumed from "WSGI is WSGI."

Sizing: for gunicorn, 2 * cpu_count + 1 worker processes is the common starting heuristic. For waitress, --threads controls a single process's thread pool; since the GIL limits true CPU-bound parallelism, more threads mainly help I/O-bound waiting overlap — start around 8–16 and measure against your own workload rather than assuming higher is always better.

ASGI: only if a view needs async def#

uvicorn config.asgi:application --workers 4 --host 0.0.0.0 --port 8000
hypercorn config.asgi:application --workers 4 --bind 0.0.0.0:8000

See ASGI for when to reach for this over WSGI.

The Rust runtime#

Settings.server.engine = 'rust' is development/load-testing tooling, not a production-server recommendation of its own — see Rust runtime for the full scope and its benchmarked result against waitress.

Reverse proxy and HTTPS#

A real deployment terminates TLS and HTTP/2 at a reverse proxy (nginx, a cloud load balancer) in front of whichever application server you chose above — trust_proxy_headers/trusted_proxy_ips in the security section tell Hayavega to trust that proxy's X-Forwarded-* headers for request.is_secure and REMOTE_ADDR.

Before deployment#

  • Settings.secret_key is a real, environment-provided secret — not the scaffolded placeholder
  • Settings.debug = False
  • Settings.allowed_hosts is your real domain list, not empty or ["*"]
  • Settings.security.force_https = True
  • python manage.py diagnose reports nothing at error severity
  • python manage.py migrationstatus shows nothing pending

Migration deployment and rollback#

Migrations are transactional and checksummed — a failed migration leaves no partial schema change where the database supports transactions. Forward-only by design; a rollback is a new, reviewed migration, not an automatic reversal.

Backup and restore#

Standard database-level backup/restore for your chosen engine (pg_dump/pg_restore for PostgreSQL, mysqldump for MySQL/MariaDB, a file copy for SQLite) — Hayavega doesn't reinvent this layer. Test a real restore drill before you need one for real.

Health and readiness#

Built-in health/readiness endpoints check real database connectivity, not just "the process is running" — wire them into your orchestrator's liveness/readiness probes.