El memory leak que tiraba el servicio cada 36 horas
Postmortem: un memory leak hacía que Kubernetes matara el pod por OOM cada día y medio. Cómo lo diagnosticamos sin reescribir la app y estabilizamos producción.
Caso anonimizado. Los detalles del cliente fueron removidos; el incidente y la intervención son reales y representativos del tipo de trabajo de MayDay.
Qué pasaba
Un SaaS B2B sufría cortes intermitentes “sin patrón” cada día y medio, casi siempre de madrugada. El equipo reiniciaba el pod y seguía. El síntoma real: Kubernetes mataba el contenedor con OOMKilled al llegar al límite de memoria — un memory leak clásico que crecía hasta tocar el techo cada ~36 horas.
No había métricas de memoria por proceso, así que se asumía “pico de tráfico”. No era tráfico: era acumulación.
Qué hicimos
- Estabilización: subimos temporalmente el límite de memoria y configuramos un reinicio controlado en ventana de bajo tráfico, para cortar las caídas de madrugada mientras buscábamos la causa — sin despertar a nadie.
- Diagnóstico: instrumentamos con heap snapshots y un dashboard de memoria en Prometheus. El leak venía de listeners de eventos que nunca se desuscribían en un cliente de websockets de larga vida.
- Blindaje: fix puntual del listener + alerta sobre la pendiente de uso de memoria (no solo el valor absoluto), para detectar el próximo leak en horas, no en días.
Resultado
- De caídas cada 36 horas a 0 reinicios por OOM en 6 semanas.
- Dashboard de memoria + alerta de tendencia: el equipo ve el leak antes que el usuario.
- No hubo que reescribir la app: se arregló lo que sangraba y se midió el resto.
Si tu servicio “se cae solo cada tanto” y lo resolvés reiniciando, no tenés un misterio: tenés un leak sin medir. Un Health Check lo encuentra.
¿Algo parecido en tu producción?
Pedí un Health Check gratis: te decimos dónde están tus riesgos reales antes de que se vuelvan un postmortem.
Pedí tu Health Check gratis →