Making Django fast
Measure first, then fix queries, caching, workers, and delivery, and prove it with a load test.
This path makes a Django site faster by fixing the biggest cost first: profiling, slow queries with query plans and indexes, N+1 patterns, caching with stampede protection, worker tuning, connection pooling, compression, and a load test before launch.
Every step starts with a measurement and ends with another, so you can see what each change bought.
The steps
- Profile Slow Django Endpoints in Production with py-spy
Find why Django endpoints are slow in production: sample live Gunicorn workers with py-spy, record flame graphs, and dump stuck workers safely.
- Find Slow Django Queries with pg_stat_statements
Enable pg_stat_statements for a Django app, rank queries by total time, trace them back to ORM code, confirm plans with EXPLAIN ANALYZE, and fix them with indexes and better querysets.
- Use QuerySet.explain() and EXPLAIN ANALYZE to Speed Up Django Queries
Read PostgreSQL query plans for Django ORM queries with QuerySet.explain(analyze=True, buffers=True): spot sequential scans, bad row estimates, sorts, and nested loops, run EXPLAIN safely on production, and turn plans into indexes and queryset fixes.
- A Practical Database Indexing Strategy for Django
Decide which indexes a Django app needs: find slow queries, index foreign keys and filter and ordering columns, use composite, partial, covering, and expression indexes with Meta.indexes, remove unused indexes, and add them without locking production tables.
- Find and Fix N+1 Queries in Django
Find and fix N+1 queries in Django: detect them in tests and logs, use select_related, prefetch_related, Prefetch objects, and annotations correctly.
- Django Caching Strategy for Production
Choose what to cache in a Django app: HTTP caching, per-view and fragment caches, low-level caching, invalidation, stampede protection, and hit rates.
- Prevent Cache Stampedes in Django
Stop cache stampedes (dogpile effects) in Django when a popular cache key expires and hundreds of requests recompute it at once: use locks, stale-while-revalidate, jittered timeouts, background refresh, and probabilistic early expiration.
- How to Optimize Gunicorn Workers for Django
If you want to optimize Gunicorn workers for Django, the main production risk is getting concurrency wrong.
- Use Django's Built-In PostgreSQL Connection Pool
Enable Django's native psycopg 3 connection pool: sizing per process, CONN_MAX_AGE rules, health checks, Gunicorn and ASGI behavior, and PgBouncer.
- Enable Gzip and Brotli Compression for Django with Nginx
Compress Django responses and static files correctly: Nginx gzip settings, precompressed static assets, Brotli support, BREACH caveats, and checks.
- How to Load Test a Django App Before Release
Pre-release load testing answers a practical deployment question: will this Django release survive real traffic on your actual production stack.
- Django Performance Checklist Before Launch
A pre-launch performance checklist for Django: query counts and indexes, caching, static and media delivery, Gunicorn and database sizing, background work, timeouts, and a load test against targets.