Optimizing WSGIDaemonProcess Configuration: Calculating Ideal Process Count for Django Sites on mod_wsgi with 4GB RAM


2 views

When running Django applications via mod_wsgi on a 4GB RAM Ubuntu server, memory becomes the primary limiting factor. Each WSGI process typically consumes between 50-100MB of RAM (depending on your application's memory footprint). With two production-grade Django sites sharing resources, we need careful allocation.

For memory-bound systems, use this formula:

Max Processes = (Total RAM - System Reserve) / Average Process Memory Footprint
Recommended Processes = Max Processes * 0.8 (safety buffer)

For our 4GB system:

(4000MB - 1000MB system) / 80MB per process ≈ 37 processes max
37 * 0.8 ≈ 29 processes (shared between both sites)

Assuming equal traffic (similar to ServerFault/SuperUser):

# Site 1 configuration
WSGIDaemonProcess serverfault.com \
    user=www-data \
    group=www-data \
    processes=12 \
    threads=5 \
    maximum-requests=1000

# Site 2 configuration  
WSGIDaemonProcess superuser.com \
    user=www-data \
    group=www-data \
    processes=12 \
    threads=5 \
    maximum-requests=1000

Consider these additional parameters for production environments:

WSGIDaemonProcess example.com \
    processes=10 \
    threads=15 \
    display-name=%{GROUP} \
    inactivity-timeout=300 \
    queue-timeout=45 \
    socket-timeout=60

Implement monitoring to validate your configuration:

# Install mod_status
apt install apache2-utils

# Sample mod_wsgi status configuration
<Location /server-status>
    SetHandler server-status
    Require host localhost
</Location>

Key metrics to watch:

  • Memory usage per process (pmap -x <pid>)
  • Request queue times
  • CPU wait states

For critical production environments:

<VirtualHost *:80>
    WSGIDaemonProcess primary \
        processes=8 \
        threads=25 \
        umask=0002 \
        python-path=/opt/apps/myapp:/opt/apps/myapp/venv/lib/python3.10/site-packages
    
    WSGIProcessGroup primary
    WSGIApplicationGroup %{GLOBAL}
    
    WSGIRestrictProcess primary
    WSGIRestrictStdin On
    WSGIRestrictStdout On
    
    ErrorLog /var/log/apache2/django_error.log
    CustomLog /var/log/apache2/django_access.log combined
</VirtualHost>

When running Django applications through mod_wsgi, the WSGIDaemonProcess directive is crucial for performance tuning. The processes parameter determines how many Python interpreter instances will handle requests for your application.

A typical Django process on mod_wsgi consumes between 50MB-150MB RAM depending on:

  • Application complexity
  • Libraries loaded
  • Middleware configuration
  • Database connection pooling
# Example configuration for a production Django site
WSGIDaemonProcess example.com \
    user=www-data \
    group=www-data \
    processes=4 \
    threads=15 \
    python-path=/path/to/venv/lib/python3.8/site-packages

For a 4GB server running two Django sites with ServerFault/SuperUser traffic levels:

  1. Reserve 1GB for OS and other services
  2. Allocate remaining 3GB for both sites
  3. Assuming 100MB per process (average for well-optimized Django)
  4. Each site gets 1.5GB (1500MB/100MB = 15 processes total)

For two equally important sites:

# Site 1 configuration
WSGIDaemonProcess serverfault.com \
    user=www-data \
    group=www-data \
    processes=6 \
    threads=5 \
    python-home=/path/to/venv

# Site 2 configuration  
WSGIDaemonProcess superuser.com \
    user=www-data \
    group=www-data \
    processes=6 \
    threads=5 \
    python-home=/path/to/venv

Consider implementing these optimizations:

Thread-based scaling:

# Fewer processes with more threads can reduce memory overhead
WSGIDaemonProcess high_traffic.com \
    user=www-data \
    group=www-data \
    processes=3 \
    threads=25

Request timeout settings:

WSGIScriptAlias / /path/to/wsgi.py \
    process-group=serverfault.com \
    application-group=%{GLOBAL} \
    request-timeout=600

Use these commands to monitor memory usage:

# Check WSGI process memory
ps -eo pid,user,args,%mem,rss --sort=-rss | grep wsgi

# Apache server-status with mod_status
http://localhost/server-status?auto