PostgreSQL  

How to Deploy a Django App with PostgreSQL on Railway

Introduction

Railway is a popular platform that makes it easy to deploy web apps and databases quickly. In this guide, you will learn how to deploy a Django application that uses PostgreSQL on Railway. The instructions are written in simple, natural language and include all required steps, commands, and configuration examples.

Overview of the Steps

  1. Prepare your Django project for production.

  2. Add PostgreSQL dependency and database config.

  3. Configure static files and WhiteNoise.

  4. Create a requirements.txt, Procfile, and runtime.txt

  5. Push your code to GitHub (or connect a repo)

  6. Create a Railway project and add a PostgreSQL plugin.

  7. Set environment variables on Railway (DATABASE_URL, SECRET_KEY, DEBUG, ALLOWED_HOSTS)

  8. Deploy and run migrations.

  9. Collect static files and create a superuser.

  10. Troubleshoot and monitor logs

1. Prepare Your Django Project for Production

Ensure your Django project is functioning locally and utilizes a virtual environment. Install production-ready components:

python -m venv .venv
source .venv/bin/activate  # macOS / Linux
.\.venv\Scripts\activate   # Windows
pip install django gunicorn psycopg2-binary dj-database-url python-dotenv whitenoise

Key packages explained:

  • gunicorn — WSGI HTTP server for running Django in production.

  • psycopg2-binary — PostgreSQL adapter for Python.

  • dj-database-url — Parse DATABASE_URL into Django DATABASES config.

  • python-dotenv — Load .env locally (optional).

  • whitenoise — Serve static files efficiently without a separate CDN during initial setup.

2. Add PostgreSQL Dependency and Database Config

In settings.py, replace the default SQLite configuration with code that reads DATABASE_URL:

# settings.py
import os
import dj_database_url

DATABASES = {
    'default': dj_database_url.config(default='sqlite:///db.sqlite3')
}

This allows Railway to provide a DATABASE_URL environment variable that Django will use automatically.

3. Configure Static Files with WhiteNoise

Configure static files so that Django can serve them in production.

Install whitenoise (already included above) and update settings.py:

# settings.py (near top)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    # ... other middleware
]

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

# Optional: compress and cache static files
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

This config reduces latency and removes the need for a separate static server for small/medium apps.

4. Create requirements.txt, Procfile, and runtime.txt

Generate requirements.txt:

pip freeze > requirements.txt

Create a Procfile (root of repo):

web: gunicorn yourprojectname.wsgi --log-file -

Create runtime.txt to pin Python version (optional but recommended):

python-3.11.6

Replace yourprojectname with the name of the Django project folder containing wsgi.py.

5. Use Environment Variables Locally (Optional)

Create a .env file for local testing (DO NOT commit .env to git):

SECRET_KEY=your_local_secret_key
DEBUG=True
DATABASE_URL=postgres://user:pass@localhost:5432/dbname

Load it locally with python-dotenv or your chosen method.

6. Push Your Code to GitHub

Railway connects to GitHub repositories. Initialize git, commit, and push:

git init
git add .
git commit -m "Prepare app for Railway deployment"
git branch -M main
git remote add origin https://github.com/your-username/your-repo.git
git push -u origin main

7. Create a Railway Project and Add PostgreSQL

  1. Sign in to Railway.app (or create an account).

  2. Click New Project → Deploy from GitHub repo and connect your repository.

  3. After creating the project, add a PostgreSQL plugin:

    • In the Railway dashboard, click Add Plugin → Postgres.

    • Railway provisions the database and provides a DATABASE_URL variable.

Railway will also show project secrets under the Variables (environment) section.

8. Set Environment Variables on Railway

In the Railway project settings or environment variables UI, add the following variables:

  • DATABASE_URL — provided automatically by the Postgres plugin

  • SECRET_KEY — a secure secret for Django

  • DEBUG — set to False in production

  • ALLOWED_HOSTS — set to your Railway domain (e.g., your-project.up.railway.app) or * for testing

Example:

KEYVALUE
DATABASE_URL(auto from Postgres plugin)
SECRET_KEYsomelongrandomsecret
DEBUGFalse
ALLOWED_HOSTSyour-app.up.railway.app

Note: Railway masks secret values and exposes them to the runtime.

9. Configure ALLOWED_HOSTS and DEBUG in settings.py

Read Django environment variables in settings.py:

# settings.py
import os

SECRET_KEY = os.environ.get('SECRET_KEY', 'fallback-secret')
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')

This makes your settings flexible for different environments.

10. Deploy, Run Migrations, and Collect Static Files

After Railway builds your app from the GitHub repo, you need to run migrations and collect static files.

Run migrations (Railway Console / Deploy Jobs)

  • Open Railway project → Plugins → Postgres (or click the project) → Run a new job or use the Railway CLI.

You can create a deploy script in package.json or use Railway’s Web Console to run commands:

# run in Railway console or via deployment commands
python manage.py migrate
python manage.py collectstatic --noinput

Create a superuser

python manage.py createsuperuser

Railway provides a web-based shell/console where you can run these commands after deployment.

11. Using the Railway CLI (Optional)

Railway offers a CLI that can make running commands easier locally and remotely.

Install Railway CLI and login:

npm i -g railway
railway login
railway init  # link to project
railway run python manage.py migrate
railway run python manage.py collectstatic --noinput

This is helpful for automating post-deploy tasks.

12. Configure Static Media and File Uploads

If your app uses user-uploaded files (media), you should use cloud storage (S3, DigitalOcean Spaces) because Railway’s ephemeral filesystem will not persist uploads across restarts.

Example using django-storages with AWS S3:

pip install django-storages boto3

Then configure in settings.py with environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_STORAGE_BUCKET_NAME).

13. Common Errors and How to Fix Them

  • OperationalError: could not connect to server: Check DATABASE_URL and Postgres plugin status.

  • ModuleNotFoundError: Ensure all packages are in requirements.txt and Railway installed them during build.

  • Static files 404: Run collectstatic and confirm STATIC_ROOT and whitenoise settings.

  • DisallowedHost: Add your Railway domain to ALLOWED_HOSTS.

  • 500 errors after deploy: Check Railway logs (Build & Deployment logs) for stack traces.

14. Monitoring, Logs, and Health Checks

  • Use the Railway logs tab to monitor runtime errors and build logs.

  • Add health-check endpoints to your Django app (e.g., /healthz) and use external monitoring.

  • For scaling, Railway provides options to increase resources or connect to a managed CDN.

15. Optional: Dockerize Your Django App

You can deploy with Docker for more control.

Example Dockerfile (simple):

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
CMD ["gunicorn", "yourprojectname.wsgi", "--bind", "0.0.0.0:8000", "--log-file", "-"]

Then set Railway to deploy from Docker or use GitHub with Dockerfile present.

16. Security and Best Practices

  • Set DEBUG=False in production.

  • Keep SECRET_KEY secret and never commit it.

  • Use HTTPS (Railway handles TLS for the default domain).

  • Use environment-specific settings or a configuration library.

  • Offload media to a persistent storage service (S3).

Quick Checklist Before Deploying

  • requirements.txt updated

  • Procfile present

  • runtime.txt present (optional)

  • DATABASES uses dj-database-url

  • whitenoise middleware configured

  • SECRET_KEY, DEBUG, ALLOWED_HOSTS set as env vars

  • Static files collected

  • Migrations applied

Summary

Deploying a Django app with PostgreSQL on Railway is straightforward: prepare your Django settings to read DATABASE_URL, configure static files with WhiteNoise, create requirements.txt and a Procfile, push your code to GitHub, add a PostgreSQL plugin in Railway, set environment variables, run migrations, and collect static files. Use Railway’s logs and CLI for troubleshooting and automation.