Deploying a Django App on Heroku with PostgreSQL
A step-by-step guide to deploying a Django application on Heroku with a PostgreSQL database, including production settings, static files, and environment variable configuration.
Heroku is one of the fastest ways to get a Django application into production — no server management, built-in PostgreSQL, and deployments via git push. This guide walks through everything from local setup to a live URL, including the production settings you actually need.
Prerequisites
- Django project already working locally
- Heroku CLI installed
- Git initialized in your project
Step 1: Install Required Packages
pip install gunicorn psycopg2-binary dj-database-url whitenoise
- gunicorn — production WSGI server
- psycopg2-binary — PostgreSQL adapter
- dj-database-url — parses
DATABASE_URLinto Django'sDATABASESdict - whitenoise — serves static files without a separate CDN
Step 2: Update settings.py for Production
Add these settings to your settings.py. Use environment variables for sensitive values:
import os
import dj_database_url
# Security
SECRET_KEY = os.environ.get("SECRET_KEY", "your-local-dev-key")
DEBUG = os.environ.get("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "localhost").split(",")
# Database — reads DATABASE_URL env var set by Heroku automatically
DATABASES = {
"default": dj_database_url.config(
default="sqlite:///db.sqlite3",
conn_max_age=600,
ssl_require=not DEBUG,
)
}
# Static files with WhiteNoise
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware", # after SecurityMiddleware
# ... rest of middleware
]
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
Step 3: Create a Procfile
In your project root:
web: gunicorn myproject.wsgi --log-file -
Replace myproject with the name of your Django project (the directory containing wsgi.py).
Step 4: Specify the Python Runtime
Create runtime.txt in the project root:
python-3.11.9
Check Heroku's supported runtimes for the latest versions.
Step 5: Generate requirements.txt
pip freeze > requirements.txt
Step 6: Create the Heroku App
heroku login
heroku create your-app-name
Step 7: Add PostgreSQL
heroku addons:create heroku-postgresql:essential-0 --app your-app-name
Heroku automatically sets the DATABASE_URL environment variable.
Step 8: Set Environment Variables
heroku config:set SECRET_KEY="your-secret-key-here"
heroku config:set DEBUG="False"
heroku config:set ALLOWED_HOSTS="your-app-name.herokuapp.com"
Generate a secure SECRET_KEY:
python -c "import secrets; print(secrets.token_urlsafe(50))"
Step 9: Deploy
git add .
git commit -m "Configure for Heroku deployment"
heroku git:remote -a your-app-name
git push heroku main
If your default branch is
master, usegit push heroku masterinstead.
Step 10: Run Migrations and Create Superuser
heroku run python manage.py migrate
heroku run python manage.py createsuperuser
Step 11: Collect Static Files
heroku run python manage.py collectstatic --noinput
Step 12: Open Your App
heroku open
Monitoring
heroku logs --tail # stream live logs
heroku ps # check running dynos
heroku config # view all environment variables
Common Issues
DisallowedHost error — Your app domain isn't in ALLOWED_HOSTS. Update the env var:
heroku config:set ALLOWED_HOSTS="your-app-name.herokuapp.com"
Static files not loading — Ensure WhiteNoiseMiddleware is listed directly after SecurityMiddleware in MIDDLEWARE and that you've run collectstatic.
Database connection errors — psycopg2-binary may conflict with compiled versions. Try psycopg2 instead if you see binary/library errors.
Conclusion
With Heroku, a working Django app can be live in under 30 minutes. The most common pitfalls are missing production settings (DEBUG=False, ALLOWED_HOSTS, SECRET_KEY from environment) and static files not being configured with WhiteNoise. Get those right and the rest is straightforward.