Article • Aug 2026 • 1 min read

Scaling Django with Redis: Cache-Aside vs Full-Page Caching in High-Traffic Systems

Practical blueprints for handling cache stampedes, implementing probabilistic early expiration (XFetch algorithm), and managing memory eviction policies under heavy read workloads.

Dicky Joel Saputra
Dicky Joel Saputra
Backend Engineer
Scaling Django with Redis: Cache-Aside vs Full-Page Caching in High-Traffic Systems Technical Diagram

1. Anatomy of a Cache Stampede

Caching is the most effective lever for scaling high-throughput web backends, but naive key expiration policies introduce catastrophic failure modes. When a hot cache key expires under thousands of concurrent requests, every worker thread attempts to recompute the same payload simultaneously, overwhelming the database.

Distributed Mutex with Redlock

Redis distributed mutex locks ensure only one worker thread recomputes an expired key while other requests wait briefly or receive stale-while-revalidate data.

2. Implementation: XFetch Probabilistic Early Expiration

To eliminate latency spikes completely, we implemented the XFetch algorithm in Django service layers. As a key approaches its TTL, requests probabilistically trigger background recomputation before the key actually expires.

redis_xfetch_cache.py PYTHON
import time, math, random
from django.core.cache import cache

def get_user_profile_optimized(user_id: int, beta: float = 1.0):
    cache_key = f"user:{user_id}:profile"
    cached = cache.get(cache_key)
    
    if cached:
        val, delta, expiry = cached
        # XFetch: Recompute early if probability threshold is crossed
        if -(delta * beta * math.log(random.random())) > (expiry - time.time()):
            # Trigger background recomputation asynchronously
            pass
        return val
        
    # Recompute with Redis distributed lock
    with cache.lock(f"lock:{cache_key}", timeout=5):
        cached = cache.get(cache_key)
        if cached:
            return cached[0]
            
        data = db_fetch_user_profile(user_id)
        cache.set(cache_key, (data, 0.05, time.time() + 3600), 3600)
        return data

XFetch probabilistic algorithm implemented with Django cache and Redis distributed lock.

<redis-cache-performance-telemetry />

< 4.8 ms
P99 Response Time
99.4%
Cache Hit Ratio
0 (Eliminated)
Stampede Incidents
-85% Reduced
Database Read IOPS

<more_technical_deep_dives />

EndeavourOS is the Linux Distro I have always wanted
Golang Linux

EndeavourOS is the Linux Distro I have always wanted

After having to resolve a bunch of issues I was facing with Manjaro - …

Read Deep-Dive →
PostgreSQL Indexing Deep Dive: B-Tree, BRIN, and Partial Indexes for 10M+ Rows
Article

PostgreSQL Indexing Deep Dive: B-Tree, BRIN, and Partial Indexes for 10M+ Rows

When a high-volume financial transaction table crosses 10 million rows, naive sequential scans cripple …

Read Deep-Dive →
<collaborate />

Backend Running Slow? Let's Fix That.

Go concurrency, databases, deployment, docker — I handle it all, so your uptime stays solid and your system runs smooth.