Independent comparison · no paid rankings
Home / Blog / Gunicorn and Nginx: assign roles properly for Django
Technical

Gunicorn and Nginx: assign roles properly for Django

Gunicorn runs Django; Nginx serves static files and protects the socket. Swap or merge those roles and Python workers spend their time on favicons.

4 min read Updated Jul 19, 2026

Django in production: Gunicorn launched with seventeen workers "from an internet formula," Nginx proxying everything—including /static/—to Gunicorn. Gunicorn CPU hits 100% during an image crawl. Fix: nginx alias /static/ and workers cut to five—API latency drops by a third.

Standard Django production stack:


Client → Nginx (TLS, gzip, static, rate limit) → Gunicorn (WSGI) → Django

Gunicorn is not a public web server—it is a WSGI process manager. Nginx does not run Python—it must never interpret Django.

Size Gunicorn with measurement, not formula alone

Starting formula on a two-core VPS: workers = (2 × cores) + 1 → five workers.

Then refine from:

  • RAM: budget 100–300 MB per Django worker depending on the app.
  • --timeout 30: kills a stuck worker—long reports belong in Celery, not HTTP.
  • --graceful-timeout: aligned with nginx proxy_read_timeout.
  • --max-requests 1000 --max-requests-jitter 50: recycles workers to limit minor leaks.

gunicorn myproject.wsgi:application \

  --bind unix:/run/gunicorn.sock \

  --workers 5 \

  --timeout 30 \

  --access-logfile -

Typical nginx config


location /static/ {

    alias /var/www/myproject/static/;

    expires 30d;

}

location /media/ {

    alias /var/www/myproject/media/;

}

location / {

    proxy_pass http://unix:/run/gunicorn.sock;

    proxy_set_header Host $host;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_set_header X-Forwarded-Proto $scheme;

}

Set ALLOWED_HOSTS and SECURE_PROXY_SSL_HEADER in Django so HTTPS behind nginx is recognized correctly.

systemd, socket, and deploy without hard cutover

A gunicorn.service unit with User=www-data and Restart=always ensures automatic restart. Unix socket permissions must let nginx connect.

On deploy: collectstatic, then Gunicorn reload (HUP graceful). Workers finish in-flight requests before loading new code—no hard cut if timeouts align.

Async workers: caution

gevent can help if profiling shows heavy network wait (external APIs). It is not the default for database-heavy e-commerce—sync with a well-sized Postgres pool stays more predictable.

For long jobs, see Celery and queues.

Hosting and product constraints

A VPS is the minimum for serious Django production. PaaS (Railway, Clever Cloud) abstracts Gunicorn—you configure a Procfile or equivalent. Shared Python hosting rarely lets you control worker count.

The peak: overloaded Gunicorn often serves what Nginx would give for free

Audit nginx logs: if more than zero percent of static or media requests hit the Gunicorn upstream, fix aliases before adding workers.

Decide and move forward without blind spots

To put a Django stack back on solid ground:

  1. Configure nginx to serve /static/ and /media/ by alias—Gunicorn should only handle dynamic traffic.
  2. Size workers from core count and measured RAM, not a copied formula.
  3. Align timeouts between nginx and Gunicorn to avoid mid-request cuts.
  4. Offload exports and reports over thirty seconds to Celery or a queue.
  5. Script graceful reload on deploy—collectstatic, HUP, HTTP smoke test.

For Postgres connection pooling, see Connection pooling. To compare VPS hosts, browse our directory.

Frequently asked questions

How many Gunicorn workers?

Start with (2 × cores) + 1, then adjust from RAM and real load measurements.

Does Nginx serve Django static files?

Yes—collectstatic into an nginx alias folder. Gunicorn should not serve CSS, JS, or media.

Unix socket or TCP?

Unix socket on the same machine; TCP localhost for containerized setups.

sync vs gevent?

sync by default; gevent only if profiling proves network wait dominates.


Gunicorn runs Django; Nginx runs the rest—confusing the two means paying Python to serve PNGs.

Compare European hosts

Filter by compliance, location and use case — then open the sheets to verify the real scope.

Browse the directory
Blog

Related reading

All articles →