To deploy a Django app on Heroku in 2026, add a Procfile containing web: gunicorn project.wsgi, pin your Python version, list gunicorn, dj-database-url, whitenoise and psycopg[binary] in requirements.txt, then run heroku create, git push heroku main and heroku run python manage.py migrate. The one thing that changed since older tutorials: Heroku removed its free tier in November 2022, so you now deploy onto a paid Eco or Basic dyno — there is no free option anymore.
Heroku is still one of the fastest ways to ship a Django project: you push to git and the platform builds your app, installs dependencies, collects static files and starts your web process. This guide covers the modern workflow end to end, the production settings that trip people up (ALLOWED_HOSTS, DEBUG, static files), and honest alternatives if you specifically need a free tier.
Key takeaways
- Heroku has no free tier since November 2022 — the cheapest options are the paid Eco and Basic dynos (check heroku.com for current plans).
- A working Django deploy needs four files:
requirements.txt, aProcfile, a Python version file (.python-version), and production-readysettings.py. - Use
dj-database-urlto read Heroku'sDATABASE_URLandWhiteNoiseto serve static files without S3. - Deploy with
git push heroku main(notmaster) and apply migrations withheroku run python manage.py migrate. - Set
DEBUG=Falseand a correctALLOWED_HOSTSvia config vars before going live. - If you need a genuinely free option, look at Render, Railway or Fly.io — compared below.
Is Heroku still free in 2026?
No. Heroku shut down all of its free product plans on 28 November 2022, including free dynos, free Postgres and free Redis. Many older Django-on-Heroku tutorials still tell you to deploy for free — that advice is out of date.
Today the entry-level dynos are Eco and Basic (both paid), and managed Postgres starts at the Essential tiers. We don't quote dollar figures here because Heroku adjusts plan pricing periodically — always confirm the current numbers on heroku.com. The Eco dyno plan lets a dyno sleep after inactivity, which keeps a hobby setup inexpensive.
If a free tier is a hard requirement, see the alternatives in the next section — Render, Railway and Fly.io all still offer some free or trial usage.
Heroku vs Render vs Railway vs Fly.io vs AWS Elastic Beanstalk
Many readers arrive looking for the old free Heroku. Here is an honest comparison of the platforms Django developers most often choose in 2026.
| Platform | Free tier? | Managed Postgres | Ease of setup | Scaling | Best for |
|---|---|---|---|---|---|
| Heroku | No (ended Nov 2022) | Yes (add-on) | Very easy | Manual or auto dynos | Teams wanting a proven git-push PaaS |
| Render | Limited free web service (spins down) | Yes (free 90 days, then paid) | Very easy | Auto-scaling | A Heroku-style workflow on a budget |
| Railway | Trial credit, no permanent free | Yes (built-in) | Very easy | Usage-based | Fast prototypes and side projects |
| Fly.io | Pay-as-you-go with a small allowance | Yes (Fly Postgres) | Moderate | Global edge VMs | Low-latency, multi-region apps |
| AWS Elastic Beanstalk | No (you pay for EC2 and RDS) | Via Amazon RDS | Moderate to complex | Full AWS auto-scaling | Teams already on AWS needing control |
For an AWS-native path, we have a dedicated walkthrough on deploying Django on Elastic Beanstalk. If you would rather self-host on a VM, see hosting Django with Nginx and uWSGI.
What do you need before you deploy?
- A working Django project in a git repository.
- The Heroku CLI installed, plus a Heroku account.
- Python and pip locally, ideally inside a virtual environment.
- A PostgreSQL mindset: Heroku runs Postgres in production, so avoid SQLite-only assumptions in your settings.
Install the Heroku CLI from the official site, then authenticate:
heroku loginHow do you prepare your Django project for Heroku?
You need four things in your project root. Start with requirements.txt — Heroku's Python buildpack reads it to install your dependencies:
Django>=5.0
gunicorn
dj-database-url
whitenoise[brotli]
psycopg[binary]gunicorn is the production WSGI server, dj-database-url parses Heroku's DATABASE_URL, whitenoise serves static files straight from the dyno, and psycopg[binary] is the modern PostgreSQL driver (the successor to psycopg2).
Next, the Procfile (no file extension) tells Heroku what process to run. Replace project with your Django project package — the folder that holds wsgi.py:
web: gunicorn project.wsgi --log-file -
release: python manage.py migrateThe optional release: line runs database migrations automatically on every deploy, before the new dynos start — a clean, modern alternative to migrating by hand.
Then pin your Python version. Heroku now recommends a .python-version file containing just the major.minor version:
3.12(The older runtime.txt with a value like python-3.12.8 still works but is being phased out in favour of .python-version.)
Finally, make settings.py production-ready: read the database from DATABASE_URL, wire up WhiteNoise, and drive DEBUG and ALLOWED_HOSTS from environment variables.
import os
import dj_database_url
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
# Heroku serves apps from <app>.herokuapp.com (plus any custom domain)
ALLOWED_HOSTS = ['.herokuapp.com']
custom_host = os.environ.get('APP_HOST')
if custom_host:
ALLOWED_HOSTS.append(custom_host)
# Parse Heroku's DATABASE_URL into Django's DATABASES setting
DATABASES = {
'default': dj_database_url.config(
default=os.environ.get('DATABASE_URL'),
conn_max_age=600,
ssl_require=True,
)
}
# WhiteNoise must sit directly after SecurityMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ... your remaining middleware
]
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# Django 5.x static-file storage (compresses + fingerprints assets)
STORAGES = {
'default': {'BACKEND': 'django.core.files.storage.FileSystemStorage'},
'staticfiles': {'BACKEND': 'whitenoise.storage.CompressedManifestStaticFilesStorage'},
}This replaces the old DjangoWhiteNoise(application) wrapper that many 2016-era tutorials show — that API was removed years ago. The middleware-plus-STORAGES approach above is the current, supported way to serve static files.
Heroku runs python manage.py collectstatic automatically during the build, so you rarely call it yourself. To skip it, set heroku config:set DISABLE_COLLECTSTATIC=1.
How do you deploy the app to Heroku?
With the four files committed to git, create the app, provision Postgres, set your config vars, and push:
# create the app (Heroku generates a name if you omit one)
heroku create my-django-app
# provision managed Postgres (paid Essential tier)
heroku addons:create heroku-postgresql:essential-0
# production config vars
heroku config:set DEBUG=False
heroku config:set DJANGO_SECRET_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(50))')"
# deploy by pushing your main branch
git push heroku main
# run pending migrations and create an admin user
heroku run python manage.py migrate
heroku run python manage.py createsuperuser
# open the live app in your browser
heroku openNote the branch name: modern git repos use main, so push with git push heroku main. Older guides say git push heroku master — only use master if that is genuinely your default branch.
heroku config:set stores secrets (database URLs, API keys, your SECRET_KEY) as environment variables — never commit these to git. Configuring transactional email, for instance, is just another config var; see our guide on sending emails with SendGrid on Heroku.
Can you deploy Django to Heroku with Docker?
Yes. If you already containerise your app, use Heroku's Container Registry instead of the git buildpack flow:
# switch the app to the container stack
heroku stack:set container
# build and push your image, then release it
heroku container:push web
heroku container:release webYou can also commit a heroku.yml manifest to build from your Dockerfile on every git push. If you are new to containerising Django, start with our walkthrough on deploying a Django project in a Docker container.
Common Heroku deployment errors (and fixes)
- Static files or CSS not loading — confirm WhiteNoise is in
MIDDLEWARE,STATIC_ROOTis set, andcollectstaticran during the build. TheCompressedManifestStaticFilesStoragebackend handles hashing and compression. DisallowedHost/Bad Request (400)— add.herokuapp.com(and any custom domain) toALLOWED_HOSTS.- App boots but shows debug pages — you left
DEBUG=True. Always run production withDEBUG=False. relation does not exist— you skipped migrations; runheroku run python manage.py migrate(or add therelease:phase).H14 - no web processes running— yourProcfileweb line is missing or misspelled; it must readweb: gunicorn project.wsgi.- Application crashed on boot — check
heroku logs --tailfor the real traceback.
Need help shipping Django to production?
Heroku is a great starting point, but production Django often grows into Postgres tuning, background workers, CI/CD and cost control. Our team has delivered 50+ projects and can help you ship faster — explore our Django development services, or, if you are weighing a move to AWS or another platform, our cloud migration services cover the full path. We use AI-assisted workflows to ship features and fixes in days, not months.
Frequently Asked Questions
Is Heroku free for Django apps in 2026?
No. Heroku ended all free product plans on 28 November 2022. To run a Django app you now need at least a paid Eco or Basic dyno plus a paid Postgres plan. Check heroku.com for current pricing, or use Render, Railway or Fly.io if you specifically need free or trial usage.
What is a Procfile and what should it contain for Django?
A Procfile is a plain-text file in your project root that declares the commands Heroku runs. For Django the minimum is a web process started by gunicorn: web: gunicorn project.wsgi, where project is the package containing wsgi.py. You can add a release: python manage.py migrate line to migrate automatically on each deploy.
How do I run Django migrations on Heroku?
Run heroku run python manage.py migrate from your terminal to apply migrations on a one-off dyno. For automation, add a release: python manage.py migrate line to your Procfile so migrations run on every deploy, before the new dynos start serving traffic.
Why are my static files not loading on Heroku?
Heroku does not serve Django static files by default. Install WhiteNoise, add whitenoise.middleware.WhiteNoiseMiddleware directly after SecurityMiddleware, set STATIC_ROOT, and use the CompressedManifestStaticFilesStorage backend. Heroku runs collectstatic during the build automatically, so your CSS and JS are then served from the dyno.
Should I push to Heroku with main or master?
Push whichever branch is actually your default. Modern git and GitHub use main, so git push heroku main is correct for most new projects. Older tutorials use git push heroku master; only use master if that is still your repository's default branch.
What are the best alternatives to Heroku for Django?
Render and Railway offer the closest Heroku-style git-push experience with managed Postgres and some free or trial usage. Fly.io is strong for low-latency, multi-region apps, while AWS Elastic Beanstalk gives the most control if you are already on AWS. Each differs in free tier, ease and scaling — see the comparison table above.