WhiteNoise vs Nginx for Django Static Files
Compare serving Django static files with WhiteNoise inside the app versus Nginx or a CDN: setup, compression and cache headers, performance, containers and PaaS, media files, and the setup that suits each deployment.
Problem statement
In production, Django does not serve static files itself, so something else must: WhiteNoise (middleware that serves them from within the Django process), Nginx (reading files from disk), or a CDN (caching them at the edge). Advice conflicts: "never serve static files from Python" versus "WhiteNoise is fine". Both statements have context. With hashed filenames and far-future cache headers, most requests for static files never reach your server at all after the first visit, which changes the calculation.
- WhiteNoise for PaaS, containers, and simple setups: no proxy configuration, compression and immutable cache headers built in, works everywhere Django runs.
- Nginx when you already run it on the same host: very efficient, keeps Python workers free, and handles media files too.
- A CDN in front of either for global audiences or heavy traffic.
- Use
CompressedManifestStaticFilesStorage(WhiteNoise) orManifestStaticFilesStorageso filenames are hashed and cacheable forever. - Media (user uploads) are different: never serve them with WhiteNoise; use Nginx, X-Accel-Redirect, or object storage.
Comparison
Setup
WhiteNoise: add the middleware right after SecurityMiddleware, set the storage backend, run collectstatic. Nginx: a location /static/ { alias ...; } block, correct permissions, and cache headers you add yourself. WhiteNoise's setup is identical on a VPS, Docker, Heroku, Render, or Cloud Run; Nginx requires a proxy you control.
Performance
Nginx serves files with sendfile from the kernel and is faster per request. WhiteNoise serves files from Python, using a worker for each request it handles. In practice, hashed filenames with Cache-Control: max-age=31536000, immutable mean browsers and CDNs request each file once per version, so the origin load is small. WhiteNoise also serves pre-compressed Brotli and gzip variants generated at collectstatic time.
Containers and PaaS
In containers, WhiteNoise keeps the image self-contained: static files are collected at build time and served by the app container, with no shared volume between app and proxy. With Nginx in a separate container, you need a shared volume or a second image that contains the static files. On PaaS without a proxy layer, WhiteNoise (or a CDN/object storage) is the practical choice.
With a CDN
Put Cloudflare, CloudFront, or another CDN in front of the site and both options become origin servers that are rarely hit. WHITENOISE_STATIC_PREFIX or STATIC_URL pointing at the CDN hostname works with either.
Media files are different
User uploads are not collected or hashed, can be large, and often need permission checks. Serve them with Nginx (alias or X-Accel-Redirect for private files) or from object storage. WhiteNoise intentionally serves only collected static files.
Explanation
Static files are immutable build artefacts: CSS, JavaScript, fonts, and images produced by collectstatic. Once filenames include a content hash, they can be cached indefinitely by browsers and CDNs, and a new deploy simply references new filenames. That property makes the origin's efficiency less important than its correctness: correct headers, compression, and availability. WhiteNoise packages those correct behaviours inside Django; Nginx provides them with more raw efficiency when you already operate it.
Edge cases / notes
- Admin static files are served the same way; missing admin CSS usually means collectstatic or serving is misconfigured.
- Vite or webpack bundles with their own hashes work with both; avoid double hashing by collecting the built files.
- HTTP/2 and HTTP/3 come from the front proxy or CDN, not WhiteNoise.
- WhiteNoise with Nginx is also fine: Nginx proxies everything to Gunicorn and WhiteNoise serves static; simpler config at a small CPU cost.
Next steps
- Set up WhiteNoise with Serve Static Files With WhiteNoise in Django.
- Add a CDN with Serve Django Static Files From CloudFront.
FAQ
Is WhiteNoise good enough for production?
Yes, especially with hashed filenames, long cache headers, and ideally a CDN in front.
Is Nginx faster than WhiteNoise?
Per request, yes. With proper caching, few requests reach either, so the difference rarely matters.
Can WhiteNoise serve media files?
No. Serve user uploads with Nginx, X-Accel-Redirect, or object storage.
Do I need both WhiteNoise and Nginx?
No. Use one to serve static files; Nginx can still proxy to Django while WhiteNoise serves them.