Caching
Caching is one of the easiest ways to make a Django app feel fast.
In this note, you will learn:
- what caching is,
- when to use it (and when not to),
- cache backends supported by Django,
- how to configure Redis as a cache backend,
- and two common caching approaches in views.
We use Redis in examples, but the core ideas apply to other backends too.
What is Caching?
Section titled “What is Caching?”Caching means storing the result of expensive work (database queries, external API calls, heavy computations) in a temporary storage called a cache.
When the same request comes again, Django can return cached data instead of recomputing everything.
In Django, caching can be done at multiple levels:
- view-level caching,
- template fragment caching,
- low-level caching (manual
cache.get()/cache.set()).
Use Caching or Not?
Section titled “Use Caching or Not?”Caching is most helpful when data is expensive to compute but does not change very often.
Example: A report page that runs heavy queries and updates only once per day.
Caching may not be a good fit for real-time or frequently changing data because users might see stale content.
Choose a caching strategy based on:
- data freshness requirements,
- request frequency,
- computation cost,
- acceptable staleness window.
Caching uses RAM and CPU resources. It can also add complexity, so monitor and test your setup.
Always validate:
- cache hit rate,
- response time improvements,
- stale-data side effects,
- invalidation behavior.
Cache Backends
Section titled “Cache Backends”Django supports several cache backends, including:
- In-Memory Cache: This is the default cache backend that stores data in memory. It is fast but not suitable for production environments as it does not persist data across server restarts.
- File-Based Cache: This backend stores cached data in files on the filesystem. It is slower than in-memory caching but can be useful for development or small applications.
- Database Cache: This backend uses a database table to store cached data. It is more persistent than in-memory caching but can add overhead to database operations.
- Memcached: This is a high-performance, distributed memory caching system that can be used in production environments to cache data across multiple servers.
- Redis: Similar to Memcached, Redis is an in-memory data structure store that can be used for caching. It offers additional features like persistence and support for complex data types.
Demo Slow API Endpoint
Section titled “Demo Slow API Endpoint”Let us first create a deliberately slow endpoint so the caching improvement is easy to observe.
from rest_framework.decorators import api_viewfrom rest_framework.response import Responseimport requests
@api_view(['GET'])def slow_api(request): data = requests.get("https://httpbin.org/delay/3").json() # Simulate a slow API call with a 3-second delay return Response(data)Redis is an in-memory data store and one of the most common production cache backends for Django.
To use Redis with Django caching, install django-redis and configure CACHES in settings.
Installing and Configuring Redis and Caching
Section titled “Installing and Configuring Redis and Caching”-
Add Redis service(s) to your
docker-compose.yml:services:redis:image: rediscontainer_name: redisrestart: alwaysports:- 6379:6379volumes:- ./data/redis:/datacommand: ["redis-server", "--appendonly", "yes"] # Enable data persistence (optional)redisinsight:image: redislabs/redisinsightcontainer_name: redisinsightports:- 8001:8001volumes:- ./data/redisinsight:/db -
Start the Redis service using Docker Compose:
Terminal window docker compose up -d redis redisinsightYou may also use
docker-composeif that is what your system supports. -
Install the
django-redispackage:Docs: https://github.com/jazzband/django-redis
Terminal window uv add django-redis -
Configure your Django settings to use Redis as the cache backend:
# settings.pyimport osCACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": os.getenv("REDIS_URL", "redis://localhost:6379/3"),"TIMEOUT": 60 * 15, # Cache timeout in seconds (15 minutes) (optional)"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}}} -
Set up caching in your view:
There are two common ways:
- view-level caching with
cache_page(simpler, recommended), - low-level caching for custom control.
-
Function-based views:
from django.views.decorators.cache import cache_pagefrom rest_framework.decorators import api_viewfrom rest_framework.response import Responseimport requests@api_view(['GET'])@cache_page(60 * 15) # Cache for 15 minutesdef slow_api(request):data = requests.get("https://httpbin.org/delay/3").json()return Response(data) -
Class-based views:
from django.views.decorators.cache import cache_pagefrom django.utils.decorators import method_decoratorfrom rest_framework.response import Responsefrom rest_framework.views import APIViewimport requestsclass SlowAPIView(APIView):@method_decorator(cache_page(60 * 15)) # Cache for 15 minutesdef get(self, request):data = requests.get("https://httpbin.org/delay/3").json()return Response(data)
from django.core.cache import cachefrom rest_framework.decorators import api_viewfrom rest_framework.response import Responseimport requests@api_view(['GET'])def slow_api(request):key = 'slow_data'data = cache.get(key)if data is None:data = requests.get("https://httpbin.org/delay/3").json()cache.set(key, data, 60 * 15) # Cache for 15 minutesreturn Response(data)For user-specific endpoints (dashboard/profile data), avoid naive shared caching unless your cache key includes user context.
- view-level caching with
Where Can We Use Caching?
Section titled “Where Can We Use Caching?”Use caching in places where repeated requests happen and data is not changing every second:
- Public API endpoints that return the same response for many users.
- Heavy list pages with filtering/sorting that hit the database frequently.
- Dashboard cards/statistics recalculated on every refresh.
- External API integrations with rate limits or slow responses.
- Template fragments like sidebars, category lists, and popular-post widgets.
- Expensive computed results such as recommendation sets or report summaries.
Avoid or carefully design caching for:
- Real-time data (stock ticker, live match score, live chat).
- Highly personalized or permission-sensitive responses unless cache keys are scoped correctly.
- Critical flows where stale data could cause incorrect decisions (for example, payment balance checks).