Enhancing Django Application Concurrency with uWSGI and Nginx

The default Django development server operates on a single thread, handling requests sequentially. This means a second request must wait for the first to complete before processing begins, leading to blocking behavior unsuitable for production workloads.

To achieve high concurrency, a common approach involves deploying Django with uWSGI as the application server and Nginx as a reverse proxy. Nginx excels at managing a high volume of concurrent connections, particularly for static content, due to its efficient event-driven architecture.

Prerequisites

Verify the operating system and Django version.

$ cat /etc/os-release
$ python -m django --version

Installing and Testing uWSGI

Install uWSGI using pip.

$ pip install uwsgi

Create a simple WSGI application file to verify uWSGI functionality.

simple_app.py

def wsgi_handler(environ, start_fn):
    start_fn('200 OK', [('Content-Type', 'text/plain')])
    return [b'Test response from uWSGI.']

Start a uWSGI server with the test application.

$ uwsgi --http-socket :8080 --wsgi-file simple_app.py

Check if the server is running and accesible.

$ curl http://localhost:8080

Configuring uWSGI for a Django Project

For a Django project, it's better to use a configuration file. Navigate to your project's root directory.

django_project/uwsgi_config.ini

[uwsgi]
# Use a socket for Nginx communication
socket = 127.0.0.1:9001
# Alternatively, use HTTP for direct access during testing
# http = :9090

# Project directory
chdir = /path/to/your/django_project
# Path to the WSGI module
module = project_name.wsgi:application

# Process and thread counts
processes = 5
threads = 3

# Master process
master = true

# Socket permissions (optional for Unix socket)
# chmod-socket = 664

# Logging
logto = /var/log/uwsgi_app.log

# Reload on file changes (development)
# touch-reload = /path/to/your/django_project/reload.trigger

# Clear environment on exit
vacuum = true

Start uWSGI using this configuration.

$ uwsgi --ini uwsgi_config.ini

Installing Nginx

Install Nginx using your system's package manager.

# For CentOS/RHEL
$ yum install epel-release
$ yum install nginx

# For Ubuntu/Debian
$ apt-get update
$ apt-get install nginx

Configuring Nginx as a Reverse Proxy

Create an Nginx server block configuration for the Django application.

/etc/nginx/conf.d/django_app.conf

upstream django_backend {
    server 127.0.0.1:9001;
    # For load balancing across multiple uWSGI instances:
    # server 127.0.0.1:9002;
    # server 127.0.0.1:9003;
}

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;
    client_max_body_size 100M;

    # Serve static files directly via Nginx
    location /static/ {
        alias /path/to/your/django_project/static_root/;
        expires 30d;
        access_log off;
    }

    # Serve media files
    location /media/ {
        alias /path/to/your/django_project/media/;
        expires 30d;
        access_log off;
    }

    # Proxy all other requests to uWSGI
    location / {
        include uwsgi_params;
        uwsgi_pass django_backend;
        uwsgi_read_timeout 300;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
}

Test the Nginx configuraton and restart the service.

$ nginx -t
$ systemctl restart nginx

Managing Static Files for Production

Django's development server serves static files, but in production, Nginx should handle them. Configure Django to collect all static files into a single directory.

In your project's settings.py:

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static_root'

Run the collectstatic management command.

$ python manage.py collectstatic

Ensure the Nginx configuration's location /static/ block points to this STATIC_ROOT directory.

Verifying the Setup

Access your Django application via the server's IP address or domain name. The combined uWSGI (with multiple processes/threads) and Nginx setup will now handle concurrent requests efficiently, eliminating the blocking behavior of the default server.

Tags: Django uWSGI nginx deployment Concurrency

Posted on Tue, 02 Jun 2026 16:37:47 +0000 by LostKID