🧪 Problem-Driven Systems Lab

🗺️ Mapa de problemas#

Los 20 casos del laboratorio con su descripción técnica, síntomas y valor de negocio.


📊 Resumen visual#

#CategoríaProblema centralValor principal
⚡ 01RendimientoAPI de reportes lenta bajo carga concurrente realReducir latencia y evitar sobredimensionar infra
🔄 02RendimientoDemasiadas queries por request, ORM mal usadoBase sana = menos incidentes y menos costos
🔭 03ObservabilidadErrores sin trazabilidad, causa raíz imposible de hallarMenor MTTR y decisiones operacionales más precisas
⛓️ 04ResilienciaIntegración lenta dispara reintentos y cascadas de fallasEvitar caídas en cascada ante terceros inestables
🧠 05RendimientoMemoria y descriptores que crecen hasta degradar el sistemaEliminar reinicios silenciosos e infra innecesaria
🚚 06EntregaSoftware que funciona en dev pero falla al desplegarPublicar con menos riesgo y revertir incidentes
🏗️ 07ArquitecturaSistema legacy crítico cuya evolución es muy lenta y caraRenovar plataformas vivas sin reescritura total
🔧 08ArquitecturaMódulo clave que participa en flujos sensibles y no admite quiebresDesacople controlado de piezas críticas del negocio
🌐 09ResilienciaAPI externa con latencia, errores intermitentes y reglas cambiantesMitigar dependencia y estabilizar tu producto
💰 10ArquitecturaSolución técnica más cara y compleja de lo que el problema necesitaReducir costos y acelerar entrega con foco en el negocio
📊 11OperacionesConsultas de reporting que compiten con operación transaccionalProteger la operación diaria durante analítica pesada
🧑‍💼 12OperacionesConocimiento crítico concentrado en una sola persona o móduloReducir riesgo organizacional y mejorar continuidad
🌩️ 13RendimientoLa clave caliente de cache expira y los N llamadores golpean el origen a la vezEvitar caídas autoinfligidas y reducir capacidad reservada del origen
🚰 14RendimientoEl pool se achica en silencio hasta que no queda ninguna conexiónEliminar el reinicio preventivo del runbook y dimensionar con una fórmula
🌊 15ResilienciaEl productor va más rápido que el consumidor y la cola crece sin techoEvitar caídas por memoria y decidir explícitamente qué se sacrifica
🔁 16ResilienciaUn reintento por timeout se convierte en un segundo cobroEliminar cobros y avisos duplicados, y el costo de devolverlos
🧬 17EntregaUn ALTER TABLE sobre una tabla caliente bloquea la aplicación enteraCambiar el esquema sin ventana de mantenimiento ni 503
❄️ 18ResilienciaEl autoescalador suma instancias y la tasa de error sube con cada unaEliminar los 503 durante los escalados y escalar con confianza
🔎 19ObservabilidadLa búsqueda responde 200 y lo que devuelve está malEliminar «el producto existe pero no aparece»
🪦 20ResilienciaEl pipeline muestra cero errores mientras pierde el 14% de los mensajesEliminar la pérdida silenciosa de datos
🪦 20ResilienciaEl pipeline muestra cero errores mientras pierde el 14% de los mensajesEliminar la pérdida silenciosa de datos

🔍 Detalle por caso#


⚡ 01 — API lenta bajo carga#

Problema: La aplicación responde bien con pocos usuarios, pero degrada su latencia y estabilidad al aumentar la concurrencia. El diseño cae en filtros no sargables, patrón N+1 y procesamiento transaccional que compite con reportes pesados.

Síntomas frecuentes:

  • p95/p99 de latencia que se dispara bajo carga
  • Timeouts intermitentes al aumentar usuarios concurrentes
  • CPU y conexiones de DB saturadas

Valor: Mejorar latencia reduce abandono, mejora estabilidad operacional y evita sobredimensionar infraestructura.


🔄 02 — N+1 queries y cuellos de botella en base de datos#

Problema: La aplicación ejecuta demasiadas consultas por solicitud o usa el ORM de forma ineficiente, generando saturación de base de datos silenciosa que empeora con el tiempo.

Síntomas frecuentes:

  • Gran cantidad de queries por request en el profiler
  • CPU alta en la base con poca carga aparente de usuarios
  • Respuestas lentas al consultar listas con relaciones

Valor: Una base sana evita incidentes recurrentes, mejora rendimiento transversal y reduce costos de hardware y licenciamiento.


🔭 03 — Observabilidad deficiente y logs inútiles#

Problema: Existen errores e incidentes, pero no hay trazabilidad suficiente para identificar la causa raíz de forma rápida y confiable. Los logs registran sin contexto real.

Síntomas frecuentes:

  • Incidentes sin causa raíz identificable en tiempo razonable
  • Logs que dicen "error" pero sin correlación ni contexto
  • Alertas que disparan sin datos accionables

Valor: Buena observabilidad reduce MTTR, mejora calidad de decisión y fortalece continuidad operacional.


⛓️ 04 — Cadena de timeouts y tormentas de reintentos#

Problema: Una integración lenta o inestable dispara reintentos agresivos, bloqueos de hilo y cascadas de fallas que van afectando servicios en cadena.

Síntomas frecuentes:

  • Un fallo puntual en un servicio externo tumba el sistema propio
  • Reintentos que amplifican la carga en lugar de mitigarla
  • Tiempos de respuesta que se vuelven impredecibles

Valor: Evita caídas en cascada y mejora resiliencia frente a terceros o componentes inestables.


🧠 05 — Presión de memoria y fugas de recursos#

Problema: El sistema consume memoria, descriptores de archivo o conexiones de forma progresiva hasta degradar o caerse, generalmente sin un error explícito hasta demasiado tarde.

Síntomas frecuentes:

  • Reinicios periódicos del proceso sin error visible claro
  • Uso de memoria que crece con el tiempo sin liberarse
  • Degradación gradual de respuesta a lo largo del día

Valor: Disminuye incidentes silenciosos, reinicios inesperados y consumo innecesario de infraestructura.


🚚 06 — Pipeline roto y entrega frágil#

Problema: El software funciona correctamente en desarrollo, pero falla al desplegar, al promover cambios entre entornos o al intentar revertir incidentes con seguridad.

Síntomas frecuentes:

  • Deploys manuales, frágiles o dependientes de una persona clave
  • Imposibilidad de hacer rollback seguro y rápido
  • Diferencias entre entornos que generan bugs en producción

Valor: Permite publicar con menos riesgo, reducir incidentes de despliegue y mejorar la velocidad real de entrega.


🏗️ 07 — Modernización incremental de monolito#

Problema: El sistema legacy sigue siendo crítico, pero su evolución se vuelve lenta, riesgosa y costosa. Cambiar una parte rompe otras no relacionadas.

Síntomas frecuentes:

  • Miedo a desplegar debido al scope de cambios
  • Imposibilidad de trabajar en paralelo sin conflictos constantes
  • Acoplamiento alto que impide reutilización o separación

Valor: Permite renovar plataformas reales sin detener la operación ni asumir una reescritura total de alto riesgo.


🔧 08 — Extracción de módulo crítico sin romper operación#

Problema: Se necesita desacoplar una parte clave del sistema, pero esa parte participa en flujos sensibles con alta visibilidad y no admite interrupciones.

Síntomas frecuentes:

  • Módulos con demasiadas responsabilidades y acoplamiento alto
  • Cambios que requieren coordinación de todo el equipo
  • Imposibilidad de versionar o desplegar ese módulo de forma independiente

Valor: Reduce riesgo operacional y habilita evolución controlada de piezas críticas del negocio.


🌐 09 — Integración externa inestable#

Problema: Una API, servicio o proveedor externo introduce latencia variable, errores intermitentes o reglas cambiantes que afectan directamente la estabilidad del sistema propio.

Síntomas frecuentes:

  • Errores dependientes de un tercero que se escapan del control propio
  • Latencia que varía sin patrón predecible
  • Cambios en la API externa que rompen el sistema sin previo aviso

Valor: Mitiga la dependencia de terceros y evita que un proveedor defina la estabilidad de tu producto.


💰 10 — Arquitectura cara para un problema simple#

Problema: La solución técnica consume más servicios, complejidad y costo del que el problema de negocio realmente necesita. Se sobreingenia antes de validar.

Síntomas frecuentes:

  • Infraestructura costosa para un volumen de tráfico bajo
  • Complejidad operativa que supera el valor entregado
  • Tiempo de desarrollo elevado para funcionalidades simples

Valor: Mejora adaptabilidad, reduce costos y acelera la entrega manteniendo el foco en el problema real.


📊 11 — Reportes pesados que bloquean la operación#

Problema: Consultas y procesos de reporting compiten con la operación transaccional y degradan el sistema completo durante la generación de informes.

Síntomas frecuentes:

  • El sistema se pone lento durante reportes de fin de mes
  • Queries de análisis que fuerzan full table scans en producción
  • Base de datos compartida entre OLTP y OLAP sin separación

Valor: Protege la operación diaria y permite crecer en analítica sin romper el sistema transaccional.


🧑‍💼 12 — Punto único de conocimiento y riesgo operacional#

Problema: Una persona, módulo o procedimiento concentra tanto conocimiento que el sistema se vuelve frágil ante ausencias, rotación o vacaciones.

Síntomas frecuentes:

  • Incidentes que solo puede resolver una persona
  • Documentación de operación inexistente o desactualizada
  • Flujos críticos que nadie fuera de una persona entiende

Valor: Reduce riesgo organizacional, mejora continuidad y hace al producto más sostenible a largo plazo.


🌩️ 13 — Cache stampede y thundering herd#

Problema: Una clave de cache caliente expira y, en ese instante, todos los requests que la estaban usando encuentran el hueco a la vez. Ninguno sabe que los otros existen, así que todos van al origen a recalcular el mismo valor.

Síntomas frecuentes:

  • La base cae 90 segundos exactos a la misma hora, sin que suba el tráfico
  • Hit rate de cache al 99% y aun así picos de miles de consultas idénticas al origen
  • p99 que se dispara en escalón, no en rampa
  • Reiniciar el servicio de cache provoca la caída en vez de arreglarla

Valor: Evita caídas autoinfligidas en el momento de mayor fragilidad del sistema y reduce la capacidad que hay que reservar «por las dudas» en el origen.


🚰 14 — Agotamiento del pool de conexiones#

Problema: El pool pierde una conexión cada vez que una query lanza, porque la devolución está solo en el camino feliz. Y como la adquisición no tiene deadline, el que llega cuando ya no hay conexiones no falla: se queda.

Síntomas frecuentes:

  • «Could not get connection from pool» con tráfico moderado, no en un pico
  • La base sana: CPU bajo, pocas conexiones activas, sin queries lentas
  • El p99 desaparece del gráfico en vez de dispararse
  • Reiniciar arregla el síntoma por unas horas

Valor: Elimina el reinicio preventivo como parte del runbook y reemplaza el dimensionado por intuición con la ley de Little sobre throughput medido.


🌊 15 — Backpressure en colas de mensajes#

Problema: El productor va más rápido que el consumidor y la cola absorbe la diferencia. Sin límite, crece hasta el OOM; con límite, hay que elegir qué pasa cuando se llena — y las tres opciones cuestan algo.

Síntomas frecuentes:

  • Memoria que crece de forma monótona y OOM killer cada tantas horas
  • Throughput alto y sin errores, pero resultados minutos atrasados
  • Mensajes que se pierden sin error, sin log y sin métrica
  • Reiniciar «arregla» la memoria y pierde todo lo que había en cola

Valor: Evita caídas por memoria y pérdidas silenciosas, y convierte el sacrificio en una decisión explícita y documentada en vez de un accidente.


🔁 16 — Idempotencia y efectos duplicados#

Problema: El cliente reintenta porque el primer intento dio timeout. Pero el primer intento sí llegó — lo que se perdió fue la respuesta. Sin una forma de distinguir el reintento del pedido nuevo, el servidor cobra otra vez.

Síntomas frecuentes:

  • Cobros duplicados reportados por clientes, con el log mostrando dos pedidos
  • Emails de confirmación enviados dos o tres veces
  • El duplicado aparece más cuando el sistema está lento: más timeouts, más reintentos
  • Después de escalar de uno a dos pods empiezan a aparecer duplicados que antes no había

Valor: Elimina cobros y notificaciones duplicadas, y el costo de soporte y devolución que cada uno genera.


🧬 17 — Migración de esquema sin downtime#

Problema: Un ALTER TABLE sobre una tabla caliente toma el lock exclusivo y no lo suelta hasta terminar. El trabajo total no cambia; lo que cambia es si se cobra todo junto con la aplicación caída o repartido en lotes.

Síntomas frecuentes:

  • 503 durante toda la ventana de despliegue, y vuelve solo al terminar
  • El healthcheck en verde: el proceso está vivo, lo que falla son las peticiones
  • El pool de conexiones agotado porque todas esperan el mismo lock
  • Un ALTER TABLE que en staging tardó 200 ms tarda veinte minutos en producción

Valor: Permite cambiar el esquema de una tabla caliente sin ventana de mantenimiento, y elimina el despliegue nocturno como forma de convivir con el problema.


❄️ 18 — Arranque en frío y retraso del autoescalado#

Problema: El proceso está vivo en el milisegundo cero y /health responde 200, pero la instancia no puede servir hasta terminar de inicializar. El balanceador que enruta por liveness manda tráfico a ese hueco, y los 503 salen de una instancia que ninguna alerta considera caída.

Síntomas frecuentes:

  • 503 justo después de escalar, y solo por unos segundos
  • El healthcheck en verde durante todo el incidente
  • Latencia p99 que empeora al agregar instancias, en vez de mejorar
  • El autoescalador rebota: suma instancias, la latencia sube, suma más

Valor: Elimina los 503 durante los escalados y habilita autoescalado agresivo con confianza — que es la forma de que el autoescalado ahorre dinero en vez de mover el problema.


🔎 19 — Deriva del índice de búsqueda y CDC roto#

Problema: La aplicación escribe en la base y después en el índice de búsqueda. Son dos sistemas sin transacción común: cuando la segunda escritura falla, nadie se entera. La búsqueda sigue respondiendo 200 y lo que devuelve está mal.

Síntomas frecuentes:

  • Un cliente llama porque su producto no aparece; existe en la base
  • Un resultado de búsqueda que lleva a un 404
  • Precios o títulos viejos en los resultados, correctos al abrir el detalle
  • Un reindexado completo «lo arregla» durante unos días

Valor: Elimina la categoría entera de «el producto existe pero no aparece», que en un catálogo son productos que no se pueden comprar.


🪦 20 — La dead letter queue olvidada#

Problema: El consumidor falla, manda el mensaje a la DLQ y sigue. Sin clasificar el error, sin reintentar, sin medir la profundidad, sin alerta. El pipeline se ve sano —throughput normal, latencia normal, error rate en cero— porque los errores se fueron a otro lado. Cierra el arco del caso 15, donde la DLQ nace.

Síntomas frecuentes:

  • Nada. Es el síntoma principal y el problema entero
  • Un cliente reporta que su pedido «nunca llegó», y en la base efectivamente no está
  • Un reporte de fin de mes que no cuadra por un porcentaje pequeño y constante
  • Alguien abre la DLQ por curiosidad y encuentra cuatrocientos mil mensajes

Valor: Elimina la pérdida silenciosa de datos. Drenar la DLQ del consumidor silencioso recupera el 71,39% de sus mensajes: trabajo que se había tirado y que se podía salvar con un reintento.


🪦 20 — La dead letter queue olvidada#

Problema: El consumidor falla, manda el mensaje a la DLQ y sigue. Sin clasificar el error, sin reintentar, sin medir la profundidad, sin alerta. El pipeline se ve sano —throughput normal, latencia normal, error rate en cero— porque los errores se fueron a otro lado. Cierra el arco del caso 15, donde la DLQ nace.

Síntomas frecuentes:

  • Nada. Es el síntoma principal y el problema entero
  • Un cliente reporta que su pedido «nunca llegó», y en la base efectivamente no está
  • Un reporte de fin de mes que no cuadra por un porcentaje pequeño y constante
  • Alguien abre la DLQ por curiosidad y encuentra cuatrocientos mil mensajes

Valor: Elimina la pérdida silenciosa de datos. Drenar la DLQ del consumidor silencioso recupera el 71,39% de sus mensajes: trabajo que se había tirado y que se podía salvar con un reintento.

Ver esta carpeta en GitHub ↗