Django performance engineering starts with measurement and ends with targeted changes to the things that actually show up in profiles. Not the things you assume are slow. The framework is fast enough for most applications out of the box, and the places where it needs help are almost always the same: unoptimized database queries, missing caches, bloated template rendering, and middleware overhead that nobody has profiled. In this hub I collect the performance patterns, caching strategies, and profiling workflows that address the real bottlenecks rather than the imagined ones.
The guides below cover caching at multiple layers, ORM query optimization, database-level tuning, and the operational monitoring that tells you where time is actually going. If you are looking for deployment-specific performance concerns like connection pooling and process configuration, see the deployment hub. For the broader framework view, start with the framework overview.
Performance guides
Core performance concerns
Caching is the highest-leverage performance tool in Django. The framework supports per-view caching, template fragment caching, and low-level cache operations through a consistent API. Redis is the production standard for Django caching because it supports expiration, atomic operations, and data structures beyond simple key-value storage. The cache framework is straightforward to use, but the hard part is always invalidation: knowing when cached data is stale and having a strategy for refreshing it without cache stampedes.
Database queries are the second major performance surface. The ORM generates SQL that is usually correct but not always optimal. The key tools are select_related for eager-loading foreign key relationships, prefetch_related for many-to-many relationships, .only() and .defer() for column selection, and EXPLAIN ANALYZE for understanding how PostgreSQL executes your queries. The query optimization guide covers the decision tree for each of these tools.
Template rendering time is often overlooked. Complex template inheritance chains, heavy use of template tags, and inline queryset evaluation in templates all add up. For pages with many dynamic fragments, template fragment caching is more effective than full-page caching because it lets you cache the expensive parts independently. For pages that are mostly static, full-page caching with a CDN is the simplest and most effective approach.
Middleware overhead accumulates silently. Every middleware layer runs on every request. Session middleware that hits the database, authentication middleware that loads user objects, and custom middleware that performs lookups all add latency. Profiling the middleware stack is one of the first things to do when investigating response time issues, because the overhead is constant and applies to every request regardless of the view.
Common performance mistakes
- Optimizing based on assumptions instead of profiling. The bottleneck is rarely where you think it is.
- Adding caching everywhere without an invalidation strategy, serving stale data to users.
- Ignoring middleware overhead, which runs on every request regardless of view complexity.
- Premature optimization of code paths that are not in the critical request path.
- Using database queries in template tags, which makes query counts unpredictable and hard to profile.
What to read next
Start with the caching patterns guide if you are adding caching for the first time. For database performance, the query optimization guide and the PostgreSQL guide cover complementary concerns. For setting up the observability that makes performance work sustainable, see the logging and monitoring guide. For deployment-level performance concerns, visit the deployment hub.