Deploy Django with AZIN
Django deployment has always meant configuring Gunicorn, Nginx, static files, database connections, and a dozen environment variables. AZIN detects your Django project, sets up the WSGI server, runs collectstatic, provisions PostgreSQL, and deploys to your own GCP account. No Nginx. No Procfile. Push code, it's live.
#How AZIN detects Django
AZIN uses Railpack to auto-detect your project. When it finds manage.py and a Python dependency file (requirements.txt, pyproject.toml, or Pipfile), it identifies a Django project and configures the build automatically.
What Railpack sets up for you:
- Python version from
.python-versionorruntime.txt(defaults to 3.13) - Dependency installation via pip, Poetry, PDM, or uv based on your lockfile
- Gunicorn as the WSGI server with a sensible worker configuration
collectstaticto gather static assets before the app starts- Database migrations via
python manage.py migrateon each deploy
The default start command Railpack generates:
python manage.py migrate && gunicorn myproject.wsgiNo Procfile needed. No Dockerfile needed. If you want either, AZIN supports both — but for most Django apps, Railpack auto-detection handles everything.
#Deployment config
Connect your GitHub repo, and AZIN deploys on every push. For a Django app with PostgreSQL, here's the full azin.yaml:
name: my-django-app
cloud: gcp
region: europe-west4
services:
web:
build:
type: railpack
env:
DJANGO_SETTINGS_MODULE: myproject.settings.production
ALLOWED_HOSTS: ".azin.run,.yourdomain.com"
DEBUG: "false"
scaling:
min: 1
max: 10
target_cpu: 70
db:
type: postgres
plan: production
cache:
type: redisAZIN injects DATABASE_URL and REDIS_URL into your web service automatically. No manual connection string configuration.
#Django settings for production
Your settings.py needs a few changes for production. Use dj-database-url to parse the injected DATABASE_URL, and pull secrets from environment variables:
# settings/production.py
import os
import dj_database_url
SECRET_KEY = os.environ["SECRET_KEY"]
DEBUG = False
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "").split(",")
DATABASES = {
"default": dj_database_url.config(
default=os.environ.get("DATABASE_URL"),
conn_max_age=600,
)
}
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
# WhiteNoise for static file serving — no Nginx required
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
# ... remaining middleware
]
STORAGES = {
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
},
}Add gunicorn, dj-database-url, and whitenoise to your requirements.txt:
Django>=6.0,<6.1
gunicorn>=23.0
dj-database-url>=2.3
whitenoise>=6.8
psycopg[binary]>=3.2
That's the entire production configuration. No Nginx config files, no systemd units, no reverse proxy setup.
#Adding Celery workers
Django apps commonly need background task processing. Add a Celery worker as a separate service in azin.yaml:
name: my-django-app
cloud: gcp
region: europe-west4
services:
web:
build:
type: railpack
env:
DJANGO_SETTINGS_MODULE: myproject.settings.production
worker:
build:
type: railpack
start: celery -A myproject worker --loglevel=info
env:
DJANGO_SETTINGS_MODULE: myproject.settings.production
beat:
build:
type: railpack
start: celery -A myproject beat --loglevel=info
env:
DJANGO_SETTINGS_MODULE: myproject.settings.production
db:
type: postgres
plan: production
cache:
type: redisAll three services (web, worker, beat) share the same codebase, the same DATABASE_URL, and the same REDIS_URL. AZIN provisions Redis alongside Postgres and injects both connection strings.
#Environment variables and secrets
Django requires several environment variables in production. Set them through the AZIN dashboard. A CLI is on our roadmap — the commands below show the planned interface:
azin env set SECRET_KEY "your-production-secret-key"
azin env set ALLOWED_HOSTS ".yourdomain.com"
azin env set DEBUG "false"
azin env set DJANGO_SETTINGS_MODULE "myproject.settings.production"DATABASE_URL and REDIS_URL are injected automatically when you add database and cache services. Never hardcode these.
For sensitive values like API keys and payment credentials, AZIN encrypts environment variables at rest and injects them at runtime. They never appear in build logs or container images.
#Why AZIN for Django
Deploy to your cloud. Your Django app and Postgres database run in your own GCP account, with AWS and Azure on our roadmap. You own the infrastructure, the data, and the billing relationship with your cloud provider.
No WSGI server configuration. Railpack detects Django and configures Gunicorn with appropriate worker counts based on available CPU. The formula (2 * CPU) + 1 is applied automatically.
Managed PostgreSQL. AZIN provisions Cloud SQL in your GCP account. Automated backups, connection pooling, and scaling included. The connection string is injected as DATABASE_URL.
Scale-to-zero staging. Deploy staging environments on lttle.cloud (in early access). When no traffic hits your staging Django app, it scales to zero. No idle costs for environments you only use during development.
Django 6.0 ready. As of February 2026, Django 6.0.2 is the latest stable release. Railpack supports Python 3.8 through 3.13, covering every Django version in active support.
Deploy Guides
Host PostgreSQL with AZIN
Managed Cloud SQL in your own GCP account. Automated backups, encryption at rest, and your data never leaves your VPC.
#Related guides
- Deploy Python with AZIN -- Overview of all Python framework support on AZIN
- Deploy Flask with AZIN -- Flask's lighter-weight alternative, same zero-config GCP deployment
- Deploy Docker containers with AZIN -- For custom Dockerfile deployments
- Host PostgreSQL on AZIN -- Managed Postgres in your own cloud
- AZIN vs Heroku -- Django's historical home, now in maintenance mode
- Best Heroku alternatives in 2026 -- If you're migrating from Heroku
#Frequently asked questions
Deploy on private infrastructure
Managed AI environments with built-in isolation. Zero DevOps required.