Django có 4 level cache, đi từ thô-rộng đến mịn-hẹp.
Per-site cache (cặp UpdateCacheMiddleware + FetchFromCacheMiddleware) cache toàn bộ page response — hợp với site mostly-read như blog, landing. Per-view cache (decorator @cache_page(60 * 15) hoặc cache_page() ở URLconf) chỉ cache một view cụ thể. Template fragment ({% load cache %}{% cache 300 sidebar request.user.id %}...{% endcache %}) cache một phần của template. Low-level cache API (cache.get / cache.set) cache object/queryset bất kỳ — linh hoạt nhất.
from django.core.cache import cache
def top_posts():
key = 'top_posts:v2'
posts = cache.get(key)
if posts is None:
posts = list(Post.objects.popular()[:10])
cache.set(key, posts, timeout=300)
return postsBackend production thường là Redis (django.core.cache.backends.redis.RedisCache từ Django 4.0+).
Vấn đề khó nhất của cache luôn là invalidation — khi nào xoá key cũ? Hai pattern thường dùng: gắn signal post_save để cache.delete(), hoặc thêm version suffix vào key (top_posts:v2) rồi tăng version khi schema/format thay đổi. Tránh TTL quá dài (1 ngày) cho dữ liệu mutable, vì user sẽ thấy giá trị cũ trong nhiều giờ liền.