Back to Blog
Comparison

Django Hosting in 2026: Deploy Without Managing Servers

Recep Erdoğan11 min read
Django Hosting in 2026: Deploy Without Managing Servers

Django is one of the most productive ways to build a web application, and one of the most fiddly to put into production. The framework itself is well documented and predictable. The gap is everything around it: a WSGI or ASGI server to run the app, a reverse proxy for TLS, a real database instead of SQLite, a place to serve static files, and a plan for running migrations on every deploy. None of that is Django's job, and all of it lands on you the first time you type git push and expect a live URL.

There are two honest ways to close that gap in 2026. You can rent a plain virtual server and assemble the stack yourself, or you can use a platform that treats a Django repository as something it already understands. This comparison walks through both, shows the exact production settings Django needs, and gives you copy-paste configuration for gunicorn, ASGI, static files, migrations, and a managed Postgres database.

The short answer: Django hosting in 2026 splits into self-managed servers and managed platforms. A VPS gives full control at the cost of running gunicorn, TLS, backups, and patches yourself. A platform like Out Plane builds your repo, runs gunicorn or an ASGI worker on the PORT it assigns, provisions managed PostgreSQL, and gives you HTTPS and a domain. Start on a permanent free Hobby tier with $20 in credit, no card.

What "Django Hosting" Actually Involves

Django hosting means running the Python process that serves your application, plus the supporting pieces the framework expects in production. It is not one thing, it is a short list that has to all be true at once:

  • An application server. Django's built-in runserver is for development only. Production needs a WSGI server such as gunicorn, or an ASGI server such as uvicorn if you use async views, Channels, or websockets.
  • A bound network address. The server has to listen on 0.0.0.0 and the port the environment tells it to use, not a hard-coded 127.0.0.1:8000.
  • ALLOWED_HOSTS set correctly. Django refuses requests whose Host header is not in this list, so it must include your production domain.
  • Static files collected and served. In production Django does not serve static assets itself, so you run collectstatic and serve them through WhiteNoise or a proxy.
  • A production database. SQLite is fine locally, but production wants PostgreSQL with backups and pooling.
  • Migrations on every release. The database schema has to be brought up to date each deploy, before the new code starts taking traffic.

The two hosting models differ entirely in who does that work. On a VPS you do all of it by hand and keep doing it. On a managed platform most of it is either automatic or a single setting. The official Django deployment documentation is the authoritative reference for what production expects, and its deployment checklist is worth running through before any launch regardless of where you host.

Managed PaaS vs. VPS for Django

The choice is less about Django and more about how much operations work you want to own. Here is how the two models compare on the things that actually cost you time.

ConcernVPS (self-managed)Managed platform
App server (gunicorn/ASGI)You install and supervise itDetected and run for you
TLS and HTTPSConfigure certbot and renewalsAutomatic on every domain
DatabaseInstall and secure PostgreSQLManaged Postgres, one click
Static filesConfigure a proxy or WhiteNoiseWhiteNoise, no proxy needed
Migrations on deployWrite your own deploy scriptA release command per deploy
ScalingResize the box, add a load balancerManual scaling behind a built-in LB
OS and security patchesYour responsibilityHandled by the platform
Cost at restFixed monthly server feeFree tier, then pay-as-you-go usage
Best forFull control, learning the stackShipping and staying shipped

A VPS wins when you need root, custom system packages, or a very specific network layout, and when running the stack is part of what you want to learn. It loses on ongoing time: every patch, certificate renewal, and backup script is yours forever. A managed platform wins when your goal is a running application rather than a running server. If you want the broader picture of that tradeoff, what is a PaaS covers the model in depth.

Deploying Django Without Managing a Server

The rest of this guide uses the managed path, because the VPS path is mostly generic Linux administration. The pattern is: make three settings production-safe, tell the platform how to start the app, and let it build from git.

1. Bind to 0.0.0.0 and the assigned PORT

The single most common Django deploy failure is an app that starts fine but never receives traffic, because it is listening on the wrong address. In a container the platform assigns a port through the PORT environment variable and routes to 0.0.0.0. Your start command has to honor both.

For a standard synchronous Django app, run gunicorn against your WSGI entrypoint:

bash
gunicorn myproject.wsgi:application --bind 0.0.0.0:$PORT --workers 3

If your app uses async views, Django Channels, or websockets, run an ASGI worker instead:

bash
gunicorn myproject.asgi:application \
  -k uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:$PORT --workers 3

On Out Plane the build step detects a Python project and installs from requirements.txt automatically, so all you supply is the start command above. You can set it in the console or commit a Procfile:

web: gunicorn myproject.wsgi:application --bind 0.0.0.0:$PORT --workers 3
release: python manage.py migrate --noinput

The release line runs migrations before the new version takes traffic, which is exactly where they belong. Prefer a Dockerfile? The platform builds that too, so a hand-written image with your own base and system packages deploys the same way.

2. Make settings.py read from the environment

Production settings should come from environment variables, never from committed literals. Three of them matter most: SECRET_KEY, DEBUG, and ALLOWED_HOSTS. Django will reject requests to any host not in that last list, so it has to include your production domain.

python
import os

SECRET_KEY = os.environ["SECRET_KEY"]
DEBUG = os.environ.get("DEBUG", "0") == "1"

# Include your production domain. On Out Plane the default is
# {app}-{port}-{team}.outplane.app, plus any custom domain you add.
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "").split(",")

CSRF_TRUSTED_ORIGINS = [
    f"https://{host}" for host in ALLOWED_HOSTS if host
]

Set SECRET_KEY, DEBUG, and ALLOWED_HOSTS as environment variables in the console. Sensitive values can be marked as secrets so they are write-only after you save them, and Django reads them the same way regardless. CSRF_TRUSTED_ORIGINS is easy to forget and shows up as a 403 on your first form POST behind HTTPS, so wire it to the same host list.

3. Serve static files with WhiteNoise

In production Django hands static files off to something else. The lowest-friction option that needs no proxy is WhiteNoise, which serves compressed, cache-busted assets straight from the app process.

python
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",  # right after security
    # ... the rest of your middleware
]

STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STORAGES = {
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

Collect the files during the build so they ship inside the image:

bash
python manage.py collectstatic --noinput

For user-uploaded media that has to survive restarts, attach a persistent volume and point MEDIA_ROOT at its mount path. Static assets belong in the build; uploads belong on the volume.

4. Connect a managed PostgreSQL database

SQLite does not survive a redeploy and cannot be shared across instances, so production Django wants PostgreSQL. Provision a managed database and read its connection string from the environment. The cleanest way is dj-database-url:

python
import dj_database_url

DATABASES = {
    "default": dj_database_url.config(
        default=os.environ["DATABASE_URL"],
        conn_max_age=600,
        ssl_require=True,
    )
}

When the database and app live on the same platform, the connection string is injected as an environment variable for you, and you connect through the pooled endpoint so a few scaled instances do not exhaust the connection limit. Managed PostgreSQL on Out Plane includes automated backups, point-in-time recovery, read replicas, and connection pooling, so the database is not a second system you have to operate. If you want to start there before touching a paid tier, free PostgreSQL hosting compares the options and their limits.

5. Push and let it build

With those settings in place, deployment is a git push. The platform builds the image, runs the release migration step, starts gunicorn on the assigned port, issues a TLS certificate, and routes your domain to it. There is no cold start, so the first request after a quiet night is as fast as any other. For a fuller walkthrough with a sample repo, see how to deploy a Django application.

Scaling, Regions, and Data Residency

Once the app is live, hosting decisions become operational. Django scales horizontally well because a properly configured app keeps no state in the process: sessions live in the database or cache, uploads live on a volume or object store, and any instance can serve any request. On a managed platform you run several instances behind a load balancer that distributes traffic across them, and you adjust the instance count yourself as traffic changes; billing is usage-based, so you pay for the capacity you actually use rather than a fixed monthly box.

Where the app runs matters for data location. You can place a Django app and its database in an EU region, Nuremberg or Helsinki, for European data residency. Provisioning in one of these EU regions keeps the application and its database backups on European infrastructure, which simplifies the data-residency conversation. Residency here is about where the bytes physically sit; it is a location choice you make at provision time, not a legal jurisdiction or certification. The GDPR-compliant hosting in Europe guide covers the wider compliance picture.

Beyond the web process, a real Django deployment usually needs a couple of neighbors: a Redis instance for caching and Celery, and sometimes a background worker. You run Redis yourself as a container with a persistent volume, and additional services deploy from the same console, with internal networking, TCP ports, environment variables, deploy tokens, and a browser terminal for one-off manage.py commands all part of the platform rather than extra tools you bolt on.

Frequently Asked Questions

What is the best way to host a Django application in 2026?

The best Django hosting depends on how much operations work you want to own. A managed platform is the fastest path for most teams: it builds your repo, runs gunicorn or an ASGI worker, provisions PostgreSQL, and handles TLS, so you ship code instead of maintaining a server. A VPS is the better fit only when you need root, custom system packages, or a specific network topology.

Do I need gunicorn to deploy Django?

Yes, or an equivalent production server. Django's built-in runserver is explicitly for development and should never face the public internet. Use gunicorn for standard synchronous apps, and gunicorn with a uvicorn worker (or uvicorn directly) if you use async views, Channels, or websockets. Both must bind to 0.0.0.0 and the port the platform assigns.

Why does my Django app return a 400 Bad Request in production?

Almost always because the request's host is not in ALLOWED_HOSTS. Django rejects any request whose Host header is not listed, returning a 400. Add your production domain to ALLOWED_HOSTS, and when serving over HTTPS behind a proxy, add the matching https:// origins to CSRF_TRUSTED_ORIGINS to avoid 403s on form submissions.

How do I run Django migrations on deploy?

Run python manage.py migrate --noinput as a release step that executes before the new version takes traffic. On a platform with a release phase you declare it once, for example a release: line in a Procfile, and it runs automatically on every deploy. Doing it in the release phase rather than at container startup avoids two instances racing to migrate the same schema.

Can I run an async (ASGI) Django app in production?

Yes. Set ASGI_APPLICATION in settings, point your server at myproject.asgi:application, and run an ASGI-capable worker such as gunicorn -k uvicorn.workers.UvicornWorker. This is what you want for Django Channels, websockets, long-lived connections, or heavy use of async views. Synchronous apps are fine on plain gunicorn WSGI.

How do I serve static files when hosting Django?

Collect them with collectstatic during the build and serve them with WhiteNoise, which needs no separate proxy or CDN to get started. Add the WhiteNoise middleware right after Django's security middleware and set a manifest static-files storage backend for compression and cache busting. Keep user uploads separate on a persistent volume, since those change at runtime.

Which database should I use to host Django in production?

PostgreSQL. SQLite is convenient locally but does not survive a redeploy and cannot be shared across scaled instances. A managed PostgreSQL database gives you automated backups, point-in-time recovery, and connection pooling without operating the server yourself. Read the connection string from a DATABASE_URL environment variable and enable a bounded conn_max_age for connection reuse.

Is there a free way to host a Django app?

Yes. Out Plane offers a permanent free Hobby tier that runs one app, plus $20 in trial credit that needs no credit card, which is enough to run a small Django app with a managed Postgres database. When you outgrow the free tier, paid Pro is pay-as-you-go usage-based pricing; see pricing for current figures.

Ship Django, Not a Server

Django hosting comes down to who runs the machinery around your app. On a VPS you assemble and maintain gunicorn, TLS, PostgreSQL, static serving, and migrations by hand, and you keep maintaining them. On a managed platform those become a start command, a few environment variables, and a release step, and the platform handles the rest, including HTTPS, scaling, and patches.

If your goal is a live Django app rather than a server to babysit, set ALLOWED_HOSTS, point gunicorn at 0.0.0.0:$PORT, attach a managed database, and push. Create your app in the console, start on the free tier, and move to paid capacity in place when the traffic arrives.


Tags

django
python
hosting
paas
deployment
gunicorn

Start deploying in minutes

Connect your GitHub repository and deploy your first application today. $20 free credit. No credit card required.