Key Takeaways
runserverThe gap between "works on my machine" and "works in production" kills more Django projects than bad architecture. Most deployment failures aren't caused by complex code — they're caused by a SECRET_KEY committed to Git, a DEBUG=True that leaked into production, or a DATABASE_URL that points to SQLite instead of PostgreSQL. Pydantic eliminates this entire category of failure by validating every setting at application startup.
At Boundev, we've deployed Django applications for companies across fintech, healthtech, and SaaS — and the teams that ship reliably are the ones that treat configuration as code. This guide walks through the complete deployment pipeline: Pydantic settings, Heroku infrastructure, and the security hardening that separates hobby projects from production systems. If you need Python developers who can handle this end-to-end, we can place them in your team within 7–14 days.
Why Pydantic for Django Settings?
Django's default settings.py is a Python file with no validation, no type checking, and no guardrails. You can set DEBUG to the string "False" and Django will interpret it as True (because non-empty strings are truthy in Python). Pydantic fixes this by making settings typed, validated, and sourced from environment variables.
Traditional Django Settings:
os.getenv() returns None silently on missing varsPydantic BaseSettings:
Setting Up Pydantic Settings for Django
The setup follows a clean pattern: define a BaseSettings subclass with typed fields, load values from environment variables, and wire it into Django's settings module.
1Install Dependencies
pip install pydantic-settings python-dotenv — pydantic-settings provides the BaseSettings class, python-dotenv enables .env file loading for local development.
2Define Your Settings Class
Create a Settings class inheriting from BaseSettings with typed fields: SECRET_KEY: str, DEBUG: bool = False, ALLOWED_HOSTS: list[str], DATABASE_URL: str. Pydantic auto-reads these from environment variables.
3Configure .env for Local Dev
Add a model_config = SettingsConfigDict(env_file='.env') inside your Settings class. Locally it reads from .env; on Heroku it reads from Config Vars. Same code, different environments.
4Wire Into settings.py
Instantiate settings = Settings() at the top of your Django settings.py and reference settings.SECRET_KEY, settings.DEBUG, etc. Invalid config crashes the app at startup with a clear error — exactly what you want.
Why This Matters for Hiring: A developer who sets up Pydantic settings demonstrates production-grade thinking. When we screen Python developers at Boundev, we evaluate their approach to configuration management as a proxy for deployment maturity. Developers who use raw os.getenv() with no validation are not production-ready.
The Complete Heroku Deployment Pipeline
With Pydantic handling your settings, the Heroku deployment follows a clean, repeatable pipeline. Here's every component you need:
The Procfile: Telling Heroku How to Run Django
The Procfile is where deployment intent meets execution. A production-ready Procfile for Django includes the web process, release commands for migrations, and worker processes if you use background tasks.
Production Procfile Anatomy
Each line declares a process type that Heroku manages independently. The release phase runs automatically before each deployment completes.
web: gunicorn myproject.wsgi --workers 3 --log-file - — runs Gunicorn with 3 workers and stdout loggingrelease: python manage.py migrate --noinput — auto-migrates database on every deploy2 * CPU_cores + 1 is the Gunicorn recommendation; Heroku dynos typically support 2–4 workerscollectstatic automatically; no need to add it to ProcfileNeed Python Developers Who Ship to Production?
Boundev places pre-vetted Django developers through staff augmentation who handle the full deployment pipeline — Pydantic settings, Heroku infrastructure, CI/CD, and security hardening. Integrated into your team in 7–14 days.
Talk to Our TeamProduction Security Hardening Checklist
Security is not a feature — it's a deployment requirement. These settings should be non-negotiable in every Django production deployment. With Pydantic, each one becomes a validated, typed field that can't be accidentally misconfigured.
The Deployment Checklist
Run python manage.py check --deploy against your production settings before every deployment. This catches the most common security misconfigurations. Combined with Pydantic validation, this creates a two-layer safety net that prevents configuration-related outages.
Pydantic Settings—all secrets and env-specific config sourced from environment variables with type validation.
Procfile—web process (Gunicorn), release phase (migrate), optional worker process (Celery).
requirements.txt—all dependencies pinned to specific versions for reproducible builds.
Security audit—manage.py check --deploy passes with zero warnings in CI/CD pipeline.
Static files—WhiteNoise middleware configured with compression and caching headers.
Monitoring—Sentry for error tracking, Papertrail for log aggregation, health check endpoint.
Django Deployment: The Numbers
Why production-grade deployment practices matter for your engineering team.
FAQ
Why use Pydantic instead of django-environ for settings?
Pydantic offers compile-time type hints, runtime validation, and clear error messages that django-environ doesn't provide. With django-environ, a missing or mistyped environment variable fails silently or throws a generic error. Pydantic BaseSettings validates every field at application startup, catches type mismatches (like string "False" being truthy in Python), and provides structured error output that tells you exactly which field failed and why. It also integrates with IDE type checking, giving developers autocomplete and error detection before code runs.
How many Gunicorn workers should I use on Heroku?
The formula is (2 x CPU_cores) + 1, but Heroku dynos have specific memory constraints. For a Standard-1X dyno (512MB RAM), use 2-3 workers. For Standard-2X (1GB RAM), use 3-5 workers. Monitor memory usage with heroku logs --tail and Heroku's metrics dashboard. If you see R14 (memory quota exceeded) errors, reduce workers. For I/O-bound applications (most Django apps), consider using Gunicorn's async worker class (--worker-class gevent) to handle more concurrent connections per worker.
Should I use WhiteNoise or a CDN for static files?
Start with WhiteNoise. It serves static files directly from your Django app with gzip/Brotli compression and proper caching headers. For most applications, this is sufficient and avoids the complexity of CDN configuration. When your traffic exceeds what a single dyno can serve, or you need global edge caching, add a CDN (CloudFront, Cloudflare) in front of WhiteNoise. The architecture change is minimal because WhiteNoise already sets correct cache headers that CDNs respect.
How do I handle database migrations on Heroku?
Use the Procfile release phase: release: python manage.py migrate --noinput. This runs automatically before each deployment completes, ensuring your database schema matches your code. For zero-downtime migrations, follow Django's migration best practices: avoid destructive operations (DROP COLUMN) in the same deploy as code changes, use AddField with null=True first, then backfill data, then add constraints. At Boundev, our Django developers follow a migration safety checklist that prevents data loss during deployments.
What skills should a Django developer have for production deployment?
Beyond Django itself, production-ready developers need: environment variable management (Pydantic or similar), WSGI server configuration (Gunicorn tuning), database administration (PostgreSQL indexing, migration safety), static file serving (WhiteNoise), security hardening (HTTPS, HSTS, secure cookies), monitoring setup (Sentry, logging), and CI/CD pipeline experience (GitHub Actions, GitLab CI). Boundev screens Django developers across all these dimensions through dedicated teams, ensuring they can handle deployment end-to-end — not just write views and models.
