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_keyis a real, environment-provided secret — not the scaffolded placeholder -
Settings.debug = False -
Settings.allowed_hostsis your real domain list, not empty or["*"] -
Settings.security.force_https = True -
python manage.py diagnosereports nothing aterrorseverity -
python manage.py migrationstatusshows 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.