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
Prepare your Django project for production.
Add PostgreSQL dependency and database config.
Configure static files and WhiteNoise.
Create a requirements.txt
, Procfile
, and runtime.txt
Push your code to GitHub (or connect a repo)
Create a Railway project and add a PostgreSQL plugin.
Set environment variables on Railway (DATABASE_URL, SECRET_KEY, DEBUG, ALLOWED_HOSTS)
Deploy and run migrations.
Collect static files and create a superuser.
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
Sign in to Railway.app (or create an account).
Click New Project → Deploy from GitHub repo and connect your repository.
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:
KEY | VALUE |
---|
DATABASE_URL | (auto from Postgres plugin) |
SECRET_KEY | somelongrandomsecret |
DEBUG | False |
ALLOWED_HOSTS | your-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)
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.