django runs incredibly slow using mod_wsgi/apache unless setting WSGIApplicationGroup = %{GLOBAL}

I’ve been doing a bit of work on a django project whereby the easiest way to get things up and running seemed to be to use Apache to handle certain aspects of the project and run django via mod_wsgi.

I was able to get Django to run via the official documentation:

unfortunately, while I could at least run django but it was so slow that doing pretty much anything with the admin interface would hit Apache’s timeout 60 second limit for servicing requests and I’d get a 504 bad gateway error. Increasing the timeout up to 10 minutes would at least generally get me a response from django, but obviously that’s not acceptable performance for most practical applications.

Setting WSGIApplicationGroup = %{GLOBAL} fixes this and brings up performance somewhere near the same ballpark as the django dev server. I feel like I need to better understand why this is and whether or not that might possibly have negative consequences if at some point I want to run separate WSGI applications and/or other CGI code from the same Apache server running my in-development django project.

What I ended up setting was:

	LogLevel alert wsgi:trace6
	TimeOut 600
        WSGIScriptAlias /django /var/local/django/mysite/mysite/wsgi.py process-group=django
	WSGIDaemonProcess django python-path=/var/local/django/mysite python-home=/var/local/django/venv user=django
	WSGIApplicationGroup %{GLOBAL}
	
        
	Alias /django/static /var/local/django/mysite/static
	<Location /django/static>
		Require all granted	
	</Location>
        <Directory /var/local/django/mysite/>
        <Files wsgi.py>
		Require valid-user
        </Files>
        </Directory>

Setting WSGIApplicationGroup to e.g. “django” instead produces really slow behavior.

My application barely does more than print “hello world” type demos, most of my views don’t even have model they interact with, they just render templates based off of information included in the HTTP request itself, like printing me out a table of all the various HTTP headers included in a request. Is it possible that with recent versions of django/apache/mod_wsgi that all django applications need to run with WSGIApplicationGroup = %{GLOBAL} in order to get decent performance? If so, maybe the docs regarding running django via mod_wsgi should be updated to mention this?

For reference I’m using:

Package: apache2
Version: 2.4.52-1ubuntu4.4

Package: libapache2-mod-wsgi-py3
Version: 4.9.0-1ubuntu0.1

root@django-vm:/var/local/django/venv# bin/pip list
Package Version


asgiref 3.6.0
Django 4.1.7
pip 22.0.2
setuptools 59.6.0
sqlparse 0.4.3

In a Python 3.10.6 venv on Ubuntu 22.04

I can’t speak to your specific questions here, but I will tell you that we migrated from Apache to nginx more than 10 years ago and haven’t looked back.

Specifically, we moved to nginx precisely because of wanting to do this:

We found it far easier to do this with nginx / uwsgi than Apache. (In particular, Apache/mod_wsgi is not friendly toward running different projects under different versions of Python. It’s a whole lot easier to do that with nginx - or at least that was true in the 2010-2013 time frame, it may have changed since then, but I kinda doubt it.)

Using nginx / gunicorn is far easier

There are other options that may even be easier than nginx. (In particular, I remember a post here about another alternative that looked really interesting from a quick glance. Unfortunately, I’ve lost the link and can’t seem to find the post here.)