Production Deployment Guide
Optimal configurations for deploying your Django SaaS boilerplate on single servers of different sizes, targeting 80% resource utilization for maximum efficiency.
1. Architecture Overview
Based on the production Docker Compose configuration, the following services run on a single server:
- Django/Gunicorn: Web application server
- Celery Worker: Background task processing (optional)
- Celery Beat: Scheduled task management (optional)
- PostgreSQL: Primary database
- Redis: Message broker and caching
- Traefik: Reverse proxy and SSL termination
- Flower: Celery monitoring (optional)
2. Server Configuration Matrix
Small Server (1 vCPU, 4GB RAM)
Suitable for development/staging or small applications (~100-1000 concurrent users)
Service | Memory | CPU | Configuration |
---|---|---|---|
PostgreSQL | 1.12GB (22.4% of total) | 0.25 vCPU (20% of total) | shared_buffers=280MB, max_connections=75 |
Django/Gunicorn | 1.52GB (30.4% of total) | 0.45 vCPU (36% of total) | 6 sync workers |
Celery Worker | 720MB (14.4% of total) | 0.15 vCPU (12% of total) | concurrency=3, prefetch=1 |
Redis | 240MB (4.8% of total) | 0.05 vCPU (4% of total) | maxmemory=180MB |
System/Traefik | 400MB (8% of total) | 0.1 vCPU (8% of total) | Basic reverse proxy |
Total Usage | 3.2GB (80% of 4GB) | 0.8 vCPU (80% of 1 vCPU) | Est. Users: 100-1000 |
WEB_CONCURRENCY=6
GUNICORN_CMD_ARGS="--max-requests=1000 --max-requests-jitter=50 --timeout=30"
CELERY_WORKER_CONCURRENCY=3
CELERY_WORKER_PREFETCH_MULTIPLIER=1
REDIS_MAXMEMORY=180mb
Medium Server (2 vCPU, 8GB RAM)
Suitable for small to medium applications (~1000-4000 concurrent users)
Service | Memory | CPU | Configuration |
---|---|---|---|
PostgreSQL | 2.24GB (22.4% of total) | 0.5 vCPU (20% of total) | shared_buffers=560MB, max_connections=150 |
Django/Gunicorn | 3.04GB (30.4% of total) | 0.9 vCPU (36% of total) | WEB_CONCURRENCY=9 (gevent) |
Celery Worker | 1.44GB (14.4% of total) | 0.3 vCPU (12% of total) | concurrency=6, prefetch=2 |
Redis | 480MB (4.8% of total) | 0.1 vCPU (4% of total) | maxmemory=360MB |
System/Traefik | 800MB (8% of total) | 0.2 vCPU (8% of total) | Enhanced monitoring |
Total Usage | 6.4GB (80% of 8GB) | 1.6 vCPU (80% of 2 vCPU) | Est. Users: 1000-4000 |
WEB_CONCURRENCY=9
GUNICORN_CMD_ARGS="--worker-class=gevent --worker-connections=1000 --max-requests=1200 --preload"
CELERY_WORKER_CONCURRENCY=6
CELERY_WORKER_PREFETCH_MULTIPLIER=2
REDIS_MAXMEMORY=360mb
Large Server (4 vCPU, 16GB RAM)
Suitable for medium to large applications (~4000-12000 concurrent users)
Service | Memory | CPU | Configuration |
---|---|---|---|
PostgreSQL | 4.48GB (22.4% of total) | 1.0 vCPU (20% of total) | shared_buffers=1120MB, max_connections=250 |
Django/Gunicorn | 6.08GB (30.4% of total) | 1.8 vCPU (36% of total) | WEB_CONCURRENCY=17 (gevent) |
Celery Worker | 2.88GB (14.4% of total) | 0.6 vCPU (12% of total) | concurrency=10, prefetch=3 |
Redis | 960MB (4.8% of total) | 0.2 vCPU (4% of total) | maxmemory=720MB |
System/Traefik | 1.6GB (8% of total) | 0.4 vCPU (8% of total) | Full monitoring stack |
Total Usage | 12.8GB (80% of 16GB) | 3.2 vCPU (80% of 4 vCPU) | Est. Users: 4000-12000 |
WEB_CONCURRENCY=17
GUNICORN_CMD_ARGS="--worker-class=gevent --worker-connections=1200 --max-requests=1500 --preload"
CELERY_WORKER_CONCURRENCY=10
CELERY_WORKER_PREFETCH_MULTIPLIER=3
REDIS_MAXMEMORY=720mb
Additional Configurations: The guide also includes configurations for Extra Large (8 vCPU, 32GB RAM) and Enterprise (16 vCPU, 64GB RAM) servers, supporting up to 25,000+ concurrent users.
3. Implementation Guide
Update Docker Compose Configuration
Tweak resource limits to your docker-compose.production.yml
:
Environment Configuration
Update your .envs/production/django.env
file based on the server size.
4. Performance Optimization Tips
Application Optimization
- • Implement Redis caching for frequently accessed data
- • Use CDN for static file delivery in production
- • Consider database sessions for better scalability
- • Ensure proper indexing for frequently queried fields
-
• Use
select_related()
andprefetch_related()
in your django application to prevent N+1 query problems
Connection Pooling Configuration
Django includes built-in connection pooling via the CONN_MAX_AGE
setting:
Server Size | CONN_MAX_AGE | Max Connections | Rationale |
---|---|---|---|
1 vCPU, 4GB | 60 seconds | 75 | Balanced connection reuse |
2 vCPU, 8GB | 120 seconds | 150 | Longer reuse for performance |
4 vCPU, 16GB | 180 seconds | 250 | Extended reuse with more memory |
8 vCPU, 32GB | 300 seconds | 400 | Maximum connection reuse |
16 vCPU, 64GB | 300 seconds | 600 | Maximum reuse with enterprise capacity |
5. Monitoring & Alerts
Error Monitoring with Sentry
Sentry must be connected for production error monitoring and debugging. Without proper error tracking, identifying and fixing issues becomes extremely difficult in production environments.
To set up Sentry error monitoring:
- Visit sentry.io and create an account or log in
- Create a new project and select "Django" as the platform
-
Copy the provided
SENTRY_DSN
URL from your project settings -
Add the DSN to your environment file:
.envs/production/django.env
SENTRY_DSN=https://[email protected]/your-project-id
After adding the DSN, restart your application containers to enable error tracking and performance monitoring.
6. Scaling Considerations
Vertical Scaling Limits
Single server setup is optimal up to 16 vCPU / 64GB RAM. Beyond this point, consider horizontal scaling strategies.
Horizontal Scaling Transition
When you outgrow single-server deployments:
Database Scaling
- • Separate database server
- • Read replicas
- • Connection pooling (PgBouncer)
Application Scaling
- • Multiple app servers
- • Load balancer
- • Shared Redis cluster
Storage Scaling
- • External file storage (S3 or Google Cloud Storage)
- • CDN for static assets
- • Distributed sessions
7. Troubleshooting Common Issues
High Memory Usage
- • Check for memory leaks in Django application
- • Verify Gunicorn worker memory limits
- • Monitor PostgreSQL shared_buffers allocation
- • Review Redis memory usage patterns
High CPU Usage
- • Check for inefficient database queries
- • Monitor Celery task processing bottlenecks
- • Verify proper worker concurrency settings
- • Review application code for CPU-intensive operations
Database Connection Issues
- • Monitor PostgreSQL max_connections setting
- • Check for connection pool exhaustion
- • Verify proper connection closing in application code
Task Queue Backlog
- • Increase Celery worker concurrency
- • Monitor task execution times
- • Check for failing tasks causing retries
- • Consider scaling Celery workers horizontally
8. Frontend Assets & Tailwind Build
Before deploying to production, you must build and optimize your CSS assets for optimal performance. This section covers the Tailwind CSS build process and how to reference the minified files in your templates.
Building Minified Tailwind CSS
The project uses Tailwind CSS for styling. During development, you use the unminified output.css
file, but for production, you should build a minified version for better performance.
Building Production CSS
Navigate to the CSS utilities directory and run the build command:
cd project_name/static/jsutils
npm run tailwind:build
This command compiles and minifies your Tailwind CSS from tailwind.css
to ../css/dist.css
Automatic Environment-Specific CSS Loading
The base.html
template is already configured to automatically load the appropriate CSS file based on your environment:
{# Load different CSS files based on environment:
- output.css for development (unminified, includes all styles)
- dist.css for production (minified, optimized for performance) #}
{% if debug %}
<link href="{% static 'css/output.css' %}" rel="stylesheet" />
{% else %}
<link href="{% static 'css/dist.css' %}" rel="stylesheet" />
{% endif %}
Deployment Checklist
Before deploying to production:
Ready to launch!
Congratulations! You are now ready to launch your SaaS application. Of course it does not end here; you still need to market it. But no worries, your competition is still trying to set up the boring stuff.
Good luck! 🚀
Need Help?
If you encounter any issues during deployment or have questions about the configuration, I'm here to help!
I typically respond within 24 hours. Include your server specifications and any error messages for faster troubleshooting.