Cache stampede y thundering herd
Cuando la clave caliente expira, los N llamadores concurrentes recalculan el mismo valor y el origen recibe la rafaga entera.
📈 Que cambia para el negocio
Evita caidas autoinfligidas en el momento de mayor fragilidad del sistema y reduce la capacidad reservada del origen.
💼 Que demuestra tecnicamente
Muestra que un hit rate del 99% no protege de nada si los fallos coinciden en el tiempo, y mide el arreglo con un solo numero.
✅ Evidencia que deja
- Contrasta /cache-naive y /cache-singleflight sobre la misma rafaga con origin_computations como metrica central.
- Hace visible stampede_depth, coalesced_waiters y served_stale en cada ejecucion.
- Expone cache/state con soft TTL, hard TTL y el jitter aplicado por clave.
👀 Que mirar al ejecutarlo
- Si origin_computations sube linealmente con concurrency en naive y se queda en 1 en singleflight.
- Si coalesced_waiters da concurrency - 1: es la prueba de que el resto se colgo del mismo recalculo.
- Si el double check dentro del vuelo esta presente en los siete stacks; sin el, el patron da 3 o 4 recalculos.
Como esta resuelto en cada stack
Single-flight con la primitiva idiomatica de cada runtime: flock + double-checked locking en PHP, dict de vuelos con threading.Event en Python, Map<key, Promise> en Node, ConcurrentHashMap.computeIfAbsent atomico en Java, Lazy<Task<T>> con ExecutionAndPublication en .NET, singleflight escrito a mano con sync.WaitGroup en Go, Arc<Flight> con Mutex y Condvar en Rust
| Stack | Health check local | Compose | Detalle |
|---|---|---|---|
| 🐘 PHP 8.3 | http://localhost:8100/13/health | compose.root.yml | README del stack |
| 🐍 Python 3.12 | http://localhost:8200/13/health | compose.python.yml | README del stack |
| 🟢 Node.js 22 | http://localhost:8300/13/health | compose.nodejs.yml | README del stack |
| ☕ Java 21 | http://localhost:8400/13/health | compose.java.yml | README del stack |
| 🔵 .NET 8 | http://localhost:8500/13/health | compose.dotnet.yml | README del stack |
| 🐹 Go 1.23 | http://localhost:8600/13/health | compose.go.yml | README del stack |
| 🦀 Rust 1.83 | http://localhost:8700/13/health | compose.rust.yml | README del stack |
El expediente completo
El caso no empieza en el codigo: empieza en el sintoma y termina en el postmortem.