Latencia en sistemas distribuidos: P50, P95, P99 y presupuestos de latencia

La latencia no pertenece a un solo servicio: se acumula a lo largo del camino crítico. Cómo leerla con percentiles, presupuestarla y diagnosticarla en producción.

La API principal consume 180 ms en lógica de aplicación, la consulta a la base de datos tarda 220 ms y una dependencia externa añade otros 250 ms. Ningún componente parece catastrófico por separado. El usuario, sin embargo, espera 800 ms.

Ese desfase es el problema operativo: la latencia no pertenece a un único servicio. Es el resultado acumulado de cada conexión, cola, dependencia, reintento, bloqueo, serialización y decisión arquitectónica que forma parte del camino crítico de una solicitud.

Por eso, un análisis útil no puede limitarse a preguntar «¿qué servicio está lento?». Debe identificar dónde se consume el tiempo transcurrido, qué parte es variable, qué esperas pueden evitarse, qué trabajo puede salir del camino síncrono y si la corrección propuesta mejora el percentil visible para el usuario sin desplazar el cuello de botella hacia otro componente.

Este artículo explica cómo interpretar P50, P95, P99 y tail latency; diseñar un presupuesto end-to-end; detectar amplificación por fan-out; separar tiempo de procesamiento de tiempo de espera; e investigar una API lenta con métricas, trazas, logs y validación controlada.

La latencia es tiempo transcurrido, no velocidad

La latencia es el tiempo transcurrido entre el inicio de una operación y el momento en que su resultado queda disponible para el observador que importa.

Ese observador debe definirse explícitamente. Un backend puede registrar 120 ms de procesamiento mientras el navegador mide 430 ms desde que inicia la solicitud hasta que recibe el último byte. Ambas mediciones pueden ser correctas porque cubren límites distintos.

En una solicitud distribuida, el tiempo puede separarse en varias categorías:

CategoríaQué mideEvidencia habitual
Latencia de redTiempo empleado en atravesar rutas de redRound-trip time, pérdida de paquetes, comparación por región o ruta
Latencia de conexiónDNS, establecimiento de transporte, TLS y negociación con proxiesTiempos por fase en cliente, tasa de reutilización, spans de handshake
Latencia de procesamientoTiempo ejecutando lógica de aplicación o trabajo de base de datosPerfiles de CPU, planes de ejecución, self-time de spans
Latencia de colaTiempo esperando antes de empezar a trabajarProfundidad de cola, espera en executors, adquisición de conexiones
Latencia por contenciónTiempo esperando recursos compartidosLock waits, threads estacionados, bloqueos en base de datos
Latencia de dependenciaTiempo esperando otro servicio o datastoreClient spans, métricas de dependencia, conteo de timeouts
Latencia de serializaciónCodificación, decodificación, compresión y copias de payloadPerfiles de CPU, tamaño de payload, spans de serialización
Latencia end-to-endTiempo total visible para el usuarioRUM, pruebas sintéticas, temporizadores de edge o cliente

Reducir la latencia a «velocidad» oculta la decisión que realmente importa. Un sistema no es lento por una razón universal. Puede estar calculando lentamente, esperando capacidad, creando conexiones una y otra vez, ejecutando trabajo síncrono innecesario o amplificando una cola pequeña mediante fan-out.

El objetivo del diagnóstico es separar esos mecanismos antes de cambiar configuración.

Latencia y throughput responden preguntas distintas

Latencia y throughput están relacionados, pero no son intercambiables.

MétricaPregunta que responde
Latencia¿Cuánto tarda una operación?
Throughput¿Cuántas operaciones terminan por unidad de tiempo?

Un sistema puede presentar cualquiera de estas combinaciones:

El error de interpretación más peligroso consiste en usar throughput estable como prueba de que la latencia está sana. Un pool de workers puede seguir completando 1,000 solicitudes por segundo mientras su cola crece en 100 solicitudes por segundo. El throughput parece estable; el tiempo de respuesta ya se está deteriorando.

También existe el error inverso. Reducir concurrencia puede disminuir la latencia de cola y, al mismo tiempo, reducir el throughput máximo. Que eso sea una mejora depende del SLO, la forma de la carga y la capacidad requerida.

Por qué el promedio oculta el impacto real

Las distribuciones de latencia suelen ser asimétricas. La mayoría de las solicitudes se concentra alrededor de un rango central, mientras una fracción menor se extiende hacia una cola larga debido a cache misses, contención de locks, pausas de garbage collection, retries, conexiones frías, noisy neighbors, almacenamiento lento o dependencias saturadas.

Considera 100 solicitudes:

Ejemplo
99 solicitudes:   100 ms cada una
1 solicitud:   10,000 ms

La media aritmética es:

Cálculo
((99 × 100) + 10.000) / 100 = 199 ms

Un promedio de 199 ms puede parecer aceptable si el objetivo es 250 ms. También oculta una solicitud que tardó diez segundos.

El promedio no es falso. Responde una pregunta operacional débil: «¿cuál fue el tiempo total dividido entre el número de solicitudes?». No muestra cuántos usuarios sufrieron la cola, cuán extrema fue ni si las solicitudes afectadas compartían región, versión, operación, forma de payload o dependencia.

Los percentiles ofrecen una lectura más útil, pero siguen necesitando una población y una ventana definidas. Un P99 calculado mezclando todos los endpoints, todos los códigos de estado y un día completo puede ocultar una regresión grave en una operación crítica.

Para profundizar en cálculo de cuantiles, precisión de histogramas, ventanas de observación y alertas, consulta el artículo dedicado a cómo interpretar percentiles de latencia (P50, P95 y P99).

Cómo interpretar P50, P95, P99 y P99.9

Un percentil es un umbral dentro de una distribución observada.

Distribución de latencia con cola larga y percentiles Histograma de una distribución de latencia asimétrica: la mayoría de las solicitudes se agrupa a la izquierda y una cola larga se extiende a la derecha; las líneas P50, P95 y P99 marcan cómo P99 se adentra en la cola. latencia (ms) → frecuencia P50 P95 P99
Una distribución de latencia asimétrica: la mayoría de las solicitudes se agrupa cerca de la mediana (P50), pero la cola larga (en rojo) desplaza P95 y sobre todo P99 muy a la derecha. Por eso el promedio, atrapado cerca del centro, no describe la experiencia del 1 % más lento.

Un P99 de 1.8 segundos significa que, para la población y la ventana definidas, el 99 % de las observaciones fue de 1.8 segundos o menos. No significa que todas las solicitudes del 1 % más lento hayan tardado exactamente 1.8 segundos.

Todo percentil debe ir acompañado de tres datos:

  1. Población: endpoint, operación, clase de cliente, estado, región, versión y clase de payload.
  2. Ventana: un minuto, cinco minutos, una hora, intervalo de despliegue o periodo pico.
  3. Estimador: muestras exactas, summary del cliente, histograma clásico, histograma nativo u otra aproximación.

Los límites de buckets afectan la precisión de los cuantiles. Un P95 estimado a partir de buckets gruesos puede servir para un umbral de SLO y seguir siendo demasiado impreciso para evaluar una optimización de 20 ms. Prometheus documenta los trade-offs entre histogramas y summaries, así como el error introducido por el diseño de buckets.

No compares percentiles si su alcance y cálculo no son compatibles. Comparar un P95 del cliente móvil con un P95 del servidor sobre solicitudes exitosas puede ser útil, pero la diferencia debe interpretarse como una diferencia de límites de medición, no como una contradicción.

Por qué la tail latency se convierte en latencia del sistema

Una solicitud lenta es un evento local. Una operación distribuida que espera múltiples subsolicitudes transforma colas locales en comportamiento agregado.

Supón que un servicio llama en paralelo a 20 dependencias y no puede responder hasta que todas terminan. Si cada dependencia tiene, de forma independiente, una probabilidad del 1 % de ser «lenta», la probabilidad de que al menos una sea lenta es:

Cálculo
P(al menos una dependencia lenta)
= 1 - P(todas las dependencias rápidas)
= 1 - 0.99^20
≈ 18.2 %

La cola local del 1 % se convirtió en una probabilidad del 18.2 % de que la operación agregada encuentre al menos una rama lenta.

La independencia es solo un modelo. En producción, las dependencias suelen compartir redes, runtimes, clústeres, almacenamiento, eventos de despliegue o picos de tráfico. La ralentización correlacionada puede empeorar el comportamiento agregado respecto de lo que predice el modelo independiente. En otros casos, caches compartidas o co-localización pueden mover las ramas de forma conjunta y alterar la distribución de otra manera.

El hecho arquitectónico importante se mantiene: cuando el resultado depende de la rama más lenta, la duración máxima domina el camino crítico. El paper The Tail at Scale describe este efecto y la necesidad de construir servicios tolerantes a la cola, en lugar de asumir que componentes variables producirán por sí solos un sistema predecible.

La latencia end-to-end es un problema de camino crítico

Medir solo el servicio principal produce un modelo incompleto. El recorrido visible para el usuario puede incluir:

Recorrido end-to-end de una solicitud distribuida Cadena de etapas desde el cliente hasta la respuesta: DNS, transporte y TLS, edge o gateway, autenticación, servicio de aplicación, base de datos y dependencia externa en paralelo, serialización y retorno al cliente. Cliente Resolución DNS Transporte y TLS Edge / gateway Autenticación Servicio de aplicación Base de datos Dependencia externa Serialización Respuesta al cliente
El recorrido debe leerse como una línea temporal, no solo como una topología. La base de datos y la dependencia externa pueden ejecutarse en paralelo, por lo que sumar todas las duraciones de spans supera la latencia de reloj. Lo que fija el tiempo de respuesta es el camino crítico: la cadena más larga de trabajo causalmente dependiente desde el inicio hasta la finalización.

Una primera pregunta útil es:

¿El tiempo se consumió antes de que la solicitud llegara a la aplicación, durante el procesamiento, mientras esperaba otro recurso o durante el retorno de la respuesta?

Esa pregunta evita optimizar código cuando el coste dominante es el establecimiento de conexiones, o ampliar capacidad de base de datos cuando el span dominante es la espera para adquirir una conexión del pool.

Cómo diseñar un presupuesto de latencia

Un presupuesto de latencia convierte un objetivo vago de rendimiento en una restricción arquitectónica. Define cuánto tiempo puede consumir la operación completa y cómo se distribuye ese tiempo a lo largo del camino crítico.

Comenzar con un objetivo end-to-end

Ejemplo:

Objetivo
Objetivo de API de checkout: P95 ≤ 800 ms
Límite de medición: inicio de solicitud en cliente hasta respuesta completa
Población: solicitudes exitosas de checkout en la región primaria
Ventana: 5 minutos móviles para alertas; 28 días para reporte de SLO

El límite y la población forman parte del objetivo. «P95 menor de 800 ms» está incompleto sin ellos.

Google SRE considera la latencia una de las cuatro señales doradas y recomienda separar la latencia de solicitudes exitosas de la de solicitudes fallidas, porque los fallos pueden ser rápidos y distorsionar la distribución combinada.

Distribuir el presupuesto por componente del camino crítico

Un primer borrador podría asignar los 800 ms completos:

ComponentePresupuesto inicial
Cliente y red80 ms
API gateway40 ms
Autenticación60 ms
Servicio principal180 ms
Base de datos220 ms
Dependencia externa170 ms
Serialización50 ms
Total800 ms

La suma es correcta y el diseño es frágil. Asume que todos los componentes permanecerán simultáneamente dentro de su asignación. No existe margen para jitter de red, pausas del runtime, cache misses, efectos de despliegue, retrasos del scheduler o error de medición.

Un presupuesto operativo debe reservar holgura:

ComponenteAsignación operativa
Cliente y red70 ms
API gateway35 ms
Autenticación50 ms
Servicio principal150 ms
Base de datos180 ms
Dependencia externa160 ms
Serialización35 ms
Reserva de variabilidad y crecimiento120 ms
Objetivo total800 ms

La reserva no es tiempo sin propietario. Protege frente a variación y cambio futuro. Si se consume de forma permanente, deja de ser reserva.

Presupuesto de latencia con margen Asignación operativa de un objetivo P95 de 800 milisegundos repartido entre cliente y red, gateway, autenticación, servicio, base de datos, dependencia externa, serialización y una reserva antes del objetivo total. Cliente y red 70 ms Gateway 35 ms Autenticación 50 ms Servicio principal 150 ms Base de datos 180 ms Dependencia externa 160 ms Serialización 35 ms Reserva 120 ms Objetivo P95 total 800 ms
Un presupuesto P95 de 800 ms con asignación por componente y una reserva operativa explícita. El diagrama es conceptual: si base de datos y dependencia externa se ejecutan en paralelo, su relación se modela con el máximo de las ramas y el comportamiento del join, no con una suma serial.

Asignar usando percentiles compatibles

Un objetivo end-to-end P95 no puede garantizarse sumando simplemente el P95 de cada componente. Los percentiles no son aditivos en general, especialmente cuando las operaciones se superponen o están correlacionadas.

Usa percentiles por componente como restricciones e indicadores diagnósticos, y valida el objetivo agregado mediante mediciones end-to-end bajo tráfico representativo. Si necesitas un modelo formal, usa la distribución conjunta o simulación, en lugar de asumir que P95(A) + P95(B) equivale a P95(A + B).

Propagar deadlines a través del grafo de llamadas

El timeout downstream debe caber dentro del tiempo restante del llamador. Si una solicitud upstream tiene 300 ms antes de vencer, asignar 500 ms a una dependencia no protege el objetivo end-to-end.

Una secuencia práctica es:

Cálculo
presupuesto restante
- limpieza local y serialización de respuesta
- margen para retry, si está justificado
- margen de seguridad
= duración máxima del intento downstream

Los timeouts deben derivarse del deadline de la operación, la distribución de la dependencia y la semántica de fallo; no copiarse de un valor predeterminado del framework. El artículo sobre timeouts correctamente configurados debe concentrar la política completa de timeouts y retries.

Caso práctico: descomponer una solicitud de 800 ms

Supón que una traza muestra el siguiente camino crítico serial:

Segmento del camino críticoDuración observada
API gateway40 ms
Autenticación60 ms
Procesamiento del servicio principal180 ms
Operación de base de datos220 ms
Dependencia externa250 ms
Serialización y transferencia final de red50 ms
Total end-to-end800 ms
Cálculo
40 + 60 + 180 + 220 + 250 + 50 = 800 ms
Descomposición de una solicitud de 800 ms Descomposición serial de una solicitud de 800 milisegundos en gateway, autenticación, procesamiento, base de datos, dependencia externa como componente más grande y serialización con red, hasta el total. Gateway 40 ms Autenticación 60 ms Procesamiento 180 ms Base de datos 220 ms Dependencia externa 250 ms · componente mayor Serialización y red 50 ms Total end-to-end 800 ms
Descomposición serial de una solicitud de 800 ms. La dependencia externa (250 ms) es el componente mayor, pero «optimizar el número más grande» todavía no es una decisión: hay que evaluar variabilidad, paralelismo posible, trabajo evitable y la métrica de validación.

El componente más grande es la dependencia externa, con 250 ms, pero «optimizar el número más grande» todavía no es una decisión. Pregunta:

  1. ¿Qué componente domina el camino crítico? Aquí la llamada externa es la mayor, pero la base de datos está cerca.
  2. ¿Qué componente presenta más variabilidad? Una llamada estable de 250 ms puede influir menos en P99 que una consulta que fluctúa entre 40 ms y 1.5 segundos.
  3. ¿Qué operaciones son realmente seriales? Si base de datos y dependencia externa pueden ejecutarse en paralelo sin violar la semántica, el máximo de ambas ramas podría reemplazar su suma.
  4. ¿Qué trabajo puede salir del camino síncrono? Auditoría, enriquecimiento, notificaciones o indexación secundaria quizá no necesiten bloquear la respuesta.
  5. ¿Qué llamada puede eliminarse? Datos cacheados, precalculados, desnormalizados o transportados en la propia solicitud pueden eliminar una dependencia, pero la frescura y la corrección limitan esa decisión.
  6. ¿Dónde debe aplicarse un timeout? Debe preservar tiempo suficiente para fallback, compensación o error controlado antes del deadline upstream.
  7. ¿Cuál es la métrica de validación? El cambio debe mejorar P95 o P99 end-to-end para la operación objetivo sin introducir regresiones inaceptables de error, obsolescencia, recursos o coste.

Una optimización local que reduzca 40 ms de CPU, pero deje intacta una cola P99 de 900 ms en una dependencia, puede mejorar benchmarks sin cambiar la experiencia del usuario.

Fan-out y amplificación de latencia

Fan-out ocurre cuando una operación emite múltiples llamadas downstream. Ejecutarlas en paralelo reduce la suma de duraciones, pero el join sigue esperando la rama obligatoria más lenta.

Fan-out dominado por la rama más lenta Un servicio abre cuatro llamadas paralelas de 45, 52, 410 y 48 milisegundos; el join espera y la respuesta queda determinada por la rama de 410 milisegundos. Servicio A Dependencia 1 45 ms Dependencia 2 52 ms Dependencia 3 410 ms · rama lenta Dependencia 4 48 ms Join La respuesta espera ≈ 410 ms
Cuatro llamadas en paralelo, pero una rama de 410 ms gobierna el tiempo de respuesta. El P99 agregado puede ser materialmente peor que el P99 individual de cada dependencia, porque cada operación de usuario crea más oportunidades de encontrar una rama lenta.

El P99 agregado puede ser materialmente peor que el P99 individual de cada dependencia porque cada operación de usuario crea más oportunidades de encontrar una rama lenta. Los retries pueden añadir nuevas ramas mientras el trabajo original sigue ejecutándose, elevando la carga y la correlación.

Las respuestas posibles dependen de la semántica:

DecisiónCuándo ayudaTrade-off
Reducir fan-outAlgunas llamadas son redundantes o pueden agregarsePuede exigir rediseñar APIs o el modelo de datos
Paralelizar llamadas serialesLas llamadas son independientesAumenta la concurrencia instantánea y la carga downstream
Usar resultados parcialesNo todas las ramas son obligatoriasLa respuesta puede ser incompleta o de menor calidad
Aplicar hedgingEventos raros de cola larga dominan y duplicar es seguroAñade carga; requiere controles estrictos y cancelación
Cachear o precalcularLos datos cambian menos de lo que se consultanCostes de frescura, invalidación, memoria y consistencia
Mover trabajo a asíncronoEl usuario necesita aceptación, no finalización inmediataFinalización eventual y mayor complejidad operativa
Definir deadlines por ramaUna rama opcional no debe consumir toda la solicitudRequiere un comportamiento degradado explícito

Hedging no es un retry genérico. Emite deliberadamente un segundo intento antes de que el primero haya fallado, normalmente tras un retraso derivado de la distribución normal de latencia. Sin controles de capacidad y semántica idempotente, puede empeorar una sobrecarga.

DNS, TCP, TLS y establecimiento de conexiones

La latencia puede acumularse antes de que el procesamiento de la aplicación siquiera comience.

Una solicitud sobre una conexión fría puede requerir:

  1. resolución DNS;
  2. establecimiento de la conexión de transporte;
  3. negociación TLS;
  4. negociación con proxy o gateway;
  5. inicialización del protocolo de aplicación;
  6. recién entonces, envío de la solicitud y procesamiento en el servidor.

El establecimiento de una conexión TCP utiliza un handshake de tres pasos, especificado en RFC 9293. TLS añade negociación criptográfica y autenticación; la especificación vigente de TLS 1.3 es RFC 9846. El número real de round trips depende de la versión del protocolo, reanudación de sesión, transporte, pérdida de paquetes, middleboxes e implementación.

La distinción operativa relevante es entre conexiones frías y reutilizadas:

SeñalInterpretación probable
Tiempo DNS altoRetraso del resolver, cache misses, search domains o problema de ruta
Tiempo de conexión altoRTT, pérdida de paquetes, retransmisiones SYN, listener saturado o routing
Tiempo TLS altoHandshake completo, validación de certificados, coste criptográfico, pérdida o reanudación fallida
Baja reutilización de conexionesKeep-alive deshabilitado, vidas demasiado cortas, configuración incompatible del pool o comportamiento del proxy
Pico tras un desplieguePools reiniciados, caches vacías, nuevas instancias o churn de conexiones
Span del servidor rápido y duración del cliente lentaEl coste está fuera del límite medido por el servidor

No deduzcas la fase a partir de un único temporizador agregado. Captura tiempos por fase en el cliente cuando estén disponibles y correlaciónalos con las trazas del servidor. Un span rápido del servidor no explica el tiempo gastado antes de que el servidor reciba la solicitud.

Reutilizar conexiones suele reducir el coste de establecimiento, pero una vida ilimitada tampoco es universalmente correcta. Cambios DNS, rotación del balanceador, conexiones obsoletas, renovación de certificados o distribución desigual pueden requerir vidas acotadas y validación de salud.

Los pools de conexiones pueden eliminar o crear esperas

Un pool amortiza el coste de crear conexiones y limita el uso concurrente de un recurso downstream. También puede convertirse en una cola cuyo tiempo de espera supera al de la propia operación.

Considera esta traza:

Traza
Adquisición del pool de base de datos: 380 ms
Ejecución de la consulta:               42 ms
Decodificación del resultado:            8 ms
Span total de base de datos:            430 ms

Optimizar SQL no recuperará los 380 ms invertidos esperando una conexión.

Las señales relevantes del pool son:

Dimensionar un pool es una decisión de control de concurrencia, no una regla de tres.

Estado del poolAcción tentadoraRiesgoProceso de decisión más sólido
Pool agotado con frecuenciaAumentar el máximoSobrecargar la base de datos, aumentar locks o agotar conexiones del servidorConfirmar capacidad downstream, concurrencia de consultas, duración de transacciones y suma de pools entre instancias
Muchas conexiones ociosasReducir el poolReintroducir coste de conexión o generar ráfagas de creaciónComparar vida ociosa, forma de los picos, coste de establecimiento y límites del servidor
Espera de adquisición larga y consulta cortaAumentar el poolMover la cola hacia la base de datosProbar incrementos controlados observando CPU, I/O, lock waits, throughput y P95/P99 de consultas
Alta tasa de creaciónExtender la vidaConservar conexiones obsoletas o mal distribuidasRevisar expulsiones, resets de red, DNS, idle timeout del proxy y política de validación
Timeouts con capacidad libreAumentar el poolNo corrige leaks, deadlocks ni errores de contabilizaciónInspeccionar propiedad, devolución y transacciones bloqueadas

Un cambio válido mejora la latencia end-to-end y reduce la espera del pool sin provocar saturación downstream. Debe validarse con concurrencia representativa, no solo con una prueba de un usuario.

Cold start no describe un único problema

El término cold start suele emplearse para etiquetar cualquier lentitud en la primera solicitud. Los mecanismos subyacentes son distintos:

Cada mecanismo requiere una corrección diferente. Mantener instancias preaprovisionadas puede resolver la creación del proceso y no una cache fría. Abrir conexiones anticipadamente puede reducir el primer acceso y provocar una tormenta de conexiones durante el rollout. Calentar cada ruta posible puede alargar el despliegue y consumir recursos sin retorno.

Para diagnosticar un posible cold start, segmenta la latencia por:

Una validación útil compara las primeras N solicitudes de instancias nuevas con solicitudes en estado estable, usando la misma entrada y carga. Si solo la primera es lenta, la traza debe mostrar qué segmento de inicialización consumió el tiempo.

Colas, saturación y backpressure

La latencia suele aumentar antes de que aparezcan errores visibles. Cuando las llegadas superan la capacidad sostenible de procesamiento, el trabajo espera en una cola. El servicio puede seguir completando solicitudes y mostrar CPU promedio moderada mientras executors, particiones, conexiones o recursos downstream específicos ya están saturados.

Google SRE identifica la sobrecarga como una causa frecuente de fallos en cascada y recomienda diseñar explícitamente el comportamiento bajo overload, en lugar de permitir que colas y retries crezcan sin control.

La ley de Little aporta una relación útil en estado estable:

Fórmula
L = λ × W

Donde:

Si un servicio estable procesa 500 solicitudes por segundo y el tiempo promedio en el sistema es 200 ms:

Cálculo
L = 500 × 0,2 = 100 solicitudes en vuelo, en promedio

Si la población observada en vuelo aumenta hacia 600 mientras la tasa de llegada se mantiene cerca de 500 solicitudes por segundo, el tiempo promedio se ha desplazado hacia 1.2 segundos o el sistema ha dejado de estar en estado estable. La ecuación ayuda a detectar una inconsistencia; no demuestra dónde se produce la espera.

Crecimiento de cola antes del fallo visible Las llegadas a 600 solicitudes por segundo superan a los workers que completan 500; la cola crece 100 por segundo, el throughput parece estable mientras el tiempo de espera aumenta y produce timeouts del cliente y retries que añaden carga. Llegadas 600 req/s La cola crece +100 req/s Workers completan 500 req/s Throughput estable Aumenta la espera Timeouts del cliente Retries añaden carga
El throughput de completados puede parecer estable mientras la cola crece y el tiempo de espera aumenta. Ese retraso se convierte en timeouts del cliente y, después, en retries que suman todavía más carga: el throughput estable no prueba que la latencia esté sana.

Backpressure es el mecanismo mediante el cual un sistema comunica o impone que no puede aceptar trabajo ilimitado al ritmo actual. Según el protocolo, puede materializarse como colas acotadas, control de flujo, límites de concurrencia, admission control, rate limits, load shedding o respuestas explícitas de sobrecarga.

La decisión no es «cola o no cola». Una cola acotada puede absorber ráfagas breves. Una cola sin límite convierte overload en crecimiento de memoria y trabajo obsoleto. Una cola demasiado pequeña puede rechazar picos inofensivos. El límite depende del tiempo de espera tolerable, tasa de servicio, características de las ráfagas y semántica de fallo.

Los reintentos pueden convertir latencia en sobrecarga

Un retry consume tiempo y genera trabajo adicional. Solo se justifica cuando el fallo es transitorio, la operación puede repetirse de forma segura, queda deadline suficiente y la carga añadida no dificulta la recuperación.

Los retries en varias capas son especialmente peligrosos. Supón que tres capas permiten tres intentos totales: el intento inicial más dos reintentos. En el peor caso, una operación original puede producir:

Cálculo
3 × 3 × 3 = 27 intentos downstream

Si cada capa permite tres reintentos adicionales, existen cuatro intentos totales por capa:

Cálculo
4 × 4 × 4 = 64 intentos downstream

La diferencia entre intentos totales y reintentos adicionales debe quedar explícita en configuración y documentación.

AWS describe los retries como «egoístas» porque consumen recursos del servidor para mejorar la probabilidad de éxito de un llamador, y recomienda timeouts, exponential backoff acotado y jitter en lugar de reintentos inmediatos y sincronizados. Google SRE también advierte que los reintentos pueden amplificar una sobrecarga y contribuir a fallos en cascada.

Tormenta de reintentos Ciclo de refuerzo: los clientes llaman a un servicio degradado que produce respuestas lentas y errores; varias capas de retry generan más intentos concurrentes que vuelven al servicio y alargan las colas, produciendo todavía más errores. Clientes Servicio degradado Colas más largas Respuestas lentas y errores Capa de retry 1 Capa de retry 2 Más intentos concurrentes reingresan al servicio
Un servicio degradado dispara reintentos en varias capas. Esos intentos reingresan al servicio, alargan las colas y generan todavía más errores: los retries consumen el mismo presupuesto de latencia y capacidad que se está investigando.

Una política defendible debe especificar:

El desarrollo completo pertenece al artículo sobre tormentas de reintentos. El punto específico aquí es que los retries consumen el mismo presupuesto de latencia y capacidad que se está investigando. Cuando la degradación se vuelve persistente, un circuit breaker puede cortar los intentos antes de que amplifiquen la caída.

Caminos síncronos y asíncronos

Mover trabajo a un camino asíncrono no elimina la latencia. Cambia qué latencia espera el usuario y dónde se gestionan la finalización, los retries, el orden y los fallos.

Dimensión de decisiónCamino síncronoCamino asíncrono
Resultado final inmediatoNormalmente disponibleNo necesariamente
Acoplamiento temporalMayorMenor entre productor y consumidor
Latencia visible para el usuarioIncluye finalización downstreamPuede incluir solo validación y aceptación
Latencia de finalizaciónCoincide con la respuestaContinúa después del acknowledgement
Comunicación de fallosRespuesta o timeout inmediatoEstado, callback, evento, polling o reconciliación
Propietario de retriesCliente o servicioConsumidor o plataforma de mensajería
ConsistenciaInmediata o cercanaA menudo eventual
Complejidad operativaMenor en flujos simplesMayor por colas, replay, orden, duplicados y poison messages

La pregunta decisiva es:

¿El usuario necesita el resultado final ahora o solo una confirmación persistente de que la solicitud fue aceptada?

Un diseño asíncrono es apropiado cuando el contrato de producto tolera finalización diferida. No lo es cuando el usuario debe saber si se reservó inventario, se concedió acceso o se confirmó una transacción antes de continuar.

Mide ambas:

Reportar solo la primera puede hacer que el sistema parezca rápido mientras el backlog crece durante minutos.

Instrumentación mínima para analizar latencia

Diagnosticar latencia exige evidencia compatible entre métricas, trazas y logs.

Métricas por operación

Como mínimo, captura:

OpenTelemetry define http.server.request.duration y http.client.request.duration como histogramas de duración HTTP en sus convenciones semánticas. Usa las convenciones soportadas por la versión de instrumentación desplegada y evita mezclar silenciosamente nombres legacy y stable en un mismo dashboard.

Separa la latencia de éxitos y fallos. Una solicitud rechazada rápidamente y una solicitud exitosa lenta representan resultados distintos. Combinarlas puede hacer que el gráfico de latencia baje durante una caída.

Trazas distribuidas

Una traza debe hacer visible el camino crítico mediante:

Las convenciones semánticas de OpenTelemetry para HTTP y bases de datos definen estructuras comunes de spans, y W3C Trace Context estandariza la propagación de traceparent y tracestate, permitiendo mantener correlación entre componentes y proveedores. Para ampliar la arquitectura de trazas, propagación y sampling, revisa observabilidad con métricas, logs y trazas.

El sampling debe corresponder al objetivo diagnóstico. Un muestreo aleatorio de baja tasa puede perder eventos P99.9. El tail-based sampling puede conservar trazas lentas o fallidas, pero añade estado en collectors, retraso, coste y nuevos modos de fallo. La elección es una decisión de arquitectura de observabilidad, no un valor predeterminado universal.

Logs estructurados

Campos útiles para investigar latencia:

Campos
trace_id
span_id
operation
route
region
version
dependency
duration_ms
queue_wait_ms
connection_wait_ms
attempt_number
outcome
error_type

No coloques identificadores sin límite, consultas completas, secretos ni payloads sensibles en labels de métricas o atributos de trazas sin control. La alta cardinalidad puede volver el sistema de telemetría caro o inutilizable precisamente durante un incidente.

Requisitos de correlación

Las métricas identifican la distribución y el segmento afectado. Las trazas explican el recorrido. Los logs aportan estado detallado y contexto de error. Los instrumentos deben compartir dimensiones estables para que un ingeniero pueda pasar de:

Métricas
Regresión P99 en operación X, región Y y versión Z

a:

Trazas
Trazas lentas de operación X, región Y y versión Z

y después a:

Logs
Logs del span dominante y resultado de su dependencia

Para un flujo completo de investigación, consulta cómo investigar un incidente con métricas, logs y trazas.

Método de producción para diagnosticar una API lenta

El orden importa. Saltar directamente a optimizar código suele desperdiciar tiempo porque el retraso dominante puede estar en una cola, una conexión o una dependencia.

Paso 1: confirmar impacto y límites de medición

Establece:

Un aumento de P99 de 700 ms a 1.4 segundos con diez solicitudes por minuto tiene una relevancia y estabilidad estadística distintas del mismo aumento con 20,000 solicitudes por segundo.

Paso 2: segmentar antes de promediar

Divide la distribución por dimensiones de baja cardinalidad:

El objetivo es encontrar una población donde la lentitud se concentre. No crees labels sin límite para conseguirlo.

Paso 3: separar procesamiento de espera

Inspecciona:

CPU baja no demuestra capacidad disponible. Un servicio bloqueado esperando un pool saturado puede mostrar poca CPU y mucha latencia. Una sola partición caliente puede estar sobrecargada mientras el promedio de la flota permanece moderado.

Paso 4: seguir la traza e identificar el camino crítico

Busca:

No sumes todos los spans. Determina cuáles forman el camino crítico de reloj.

Paso 5: comparar trazas sanas y lentas

Usa la misma operación y entradas similares. Compara:

Una traza lenta genera hipótesis. Una diferencia repetida sobre una muestra representativa aporta evidencia más sólida.

Paso 6: formular una hipótesis falsable

Hipótesis débil:

Hipótesis
La base de datos está lenta.

Hipótesis falsable:

Hipótesis
P99 aumentó porque las solicitudes de la versión 4.2 esperan una conexión de base de datos.
Predicción: las trazas lentas mostrarán más de 300 ms de adquisición y menos de 60 ms de ejecución; el problema se correlacionará con agotamiento del pool tras el nuevo límite de concurrencia.

La predicción define qué evidencia apoyaría o refutaría la afirmación.

Paso 7: mitigar en la capa correcta

Las mitigaciones posibles incluyen:

La mitigación de menor riesgo durante un incidente puede ser distinta de la solución arquitectónica permanente.

Paso 8: verificar con la métrica original visible para el usuario

Una mitigación no queda validada porque un span local sea más corto. Confirma que:

Flujo de diagnóstico de latencia Flujo desde confirmar impacto y límite, segmentar la distribución, separar procesamiento de espera, encontrar el camino crítico, comparar trazas, formular una hipótesis, mitigar y verificar percentiles end-to-end; si el objetivo no se cumple, vuelve a segmentar; si se cumple, se documenta y monitoriza. Confirmar impacto y límite Segmentar la distribución Separar procesamiento de espera Encontrar el camino crítico Comparar trazas sanas y lentas Formular hipótesis falsable Mitigar en la capa correcta Verificar percentiles end-to-end ¿Objetivo cumplido sin regresión inaceptable? Documentar y monitorizar No · vuelve a segmentar
El troubleshooting de latencia como flujo repetible guiado por evidencia: confirmar impacto, segmentar, separar cómputo de espera, hallar el camino crítico, comparar trazas, hipótesis, mitigar y verificar percentiles end-to-end. Si el objetivo no se cumple, se vuelve a segmentar; si se cumple, se documenta y monitoriza.

Diagnóstico trabajado: CPU baja y latencia alta

Supón que la API muestra:

Métricas
P50: 210 ms
P95: 920 ms
P99: 1,480 ms
Tasa de error: 0.2 %
CPU promedio: 42 %

La primera afirmación es: «La CPU está baja, por tanto no existe un problema de capacidad». Las trazas muestran otra cosa:

Trazas
Adquisición del pool de base de datos P95: 510 ms
Ejecución de consulta P95:                 58 ms
Pico de solicitudes pendientes del pool: 140
CPU de base de datos:                      37 %
Lock waits de base de datos:               bajos

La espera dominante ocurre antes de ejecutar la consulta. Aumentar el pool podría reducirla, pero solo si la base de datos y el presupuesto total de conexiones soportan más consultas concurrentes. Las siguientes comprobaciones son:

  1. capacidad total de pools sumando todas las instancias;
  2. duración de leases y posibles fugas;
  3. límites de transacción;
  4. cambio de concurrencia tras el último despliegue;
  5. máximo de conexiones y rango operativo seguro de la base de datos;
  6. throughput de consultas e I/O durante un incremento controlado.

Supón que el despliegue duplicó la concurrencia de aplicación y dejó el pool sin cambios. Un aumento controlado reduce la espera a 70 ms, eleva modestamente el P95 de consultas de 58 a 65 ms y baja el P95 end-to-end de 920 a 470 ms sin aumentar errores. Esa observación respalda la hipótesis.

Si el P95 de consultas subiera a 600 ms y los lock waits se dispararan, el aumento solo habría trasladado la cola a la base de datos. La respuesta correcta sería limitar concurrencia, reducir el tiempo de transacción o ampliar capacidad downstream; no seguir aumentando conexiones.

Errores de implementación frecuentes

1. Reportar únicamente el promedio

La media oculta la forma de la distribución y la cola. Reporta distribución, volumen y percentil relevante por operación y resultado.

2. Tratar P99 como una propiedad universal del servicio

P99 depende de población, ventana, carga, región, estado y estimador. Adjunta esas dimensiones al número.

3. Sumar spans para calcular tiempo end-to-end

Los spans hijos en paralelo se superponen. Usa duración de reloj e identifica el camino crítico.

4. Asumir que CPU baja significa ausencia de saturación

Colas, pools, locks, event loops, almacenamiento, límites downstream y particiones calientes pueden dominar con CPU promedio baja.

5. Aumentar todos los pools y límites de threads

Límites mayores pueden trasladar la espera a un recurso menos controlado y provocar contención o colapso.

6. Usar cache como parche genérico

Una cache puede reducir latencia y carga, pero introduce frescura, invalidación, consistencia, memoria y nuevos modos de fallo. Define qué datos pueden quedar obsoletos y cómo se comportan los misses.

7. Reintentar en todas las capas

Los retries en capas multiplican intentos y consumen el deadline. Asigna un propietario y un presupuesto explícito de intentos totales.

8. Configurar timeouts mayores que el deadline restante

La operación downstream continúa cuando la solicitud visible para el usuario ya está condenada. Propaga deadlines y cancela trabajo abandonado cuando sea posible.

9. Llamar cold start a todo retraso inicial

Separa inicialización de proceso, JIT, calentamiento de cache, creación de pools y efecto de primera consulta. Cada uno requiere evidencia y mitigación distintas.

10. Afirmar que el procesamiento asíncrono elimina latencia

Solo reduce la latencia de aceptación cuando el contrato permite finalización diferida. La latencia de finalización y el backlog siguen existiendo.

11. Alertar sobre percentiles volátiles sin contexto de volumen

Con muy pocas muestras, los percentiles altos pueden ser inestables. Combina alertas con umbrales de tráfico, ventanas mayores o métodos basados en SLO adecuados a la carga.

12. Optimizar un componente local sin validar el recorrido del usuario

Una consulta más rápida solo ayuda si modifica el camino crítico o crea margen necesario. Verifica el objetivo end-to-end original.

Checklist operativo

Definir

Instrumentar

Diagnosticar

Cambiar

Validar

Preguntas frecuentes

¿Cuál es una buena latencia para una API?

No existe un número universal. El objetivo depende de la interacción, protocolo, geografía, grafo de dependencias, payload, necesidad de consistencia y consecuencia de esperar. Define un SLO visible para el usuario y distribuye un presupuesto para esa operación.

¿Qué diferencia existe entre P95 y P99?

P95 es el umbral en el que terminó el 95 % de las observaciones; P99 hace lo mismo para el 99 %. P99 se adentra más en la cola. Con tráfico alto, el 1 % más lento puede representar miles o millones de solicitudes.

¿Por qué la latencia puede subir mientras la CPU permanece baja?

El servicio puede estar esperando una cola, pool, lock, base de datos, red, almacenamiento, rate limit o dependencia externa. La CPU promedio también puede ocultar un core, shard, partición o subconjunto de instancias saturado.

¿Qué es tail latency?

Es el extremo lento de la distribución, normalmente observado mediante P95, P99, P99.9 o máximos. Importa porque el fan-out aumenta la probabilidad de que una operación encuentre al menos un componente lento.

¿Cómo se construye un presupuesto de latencia?

Define un objetivo end-to-end por percentil y su límite de medición, modela el camino crítico, asigna restricciones por componente con margen, propaga deadlines, instrumenta cada espera y valida la distribución agregada bajo tráfico realista. No asumas que los percentiles se suman aritméticamente.

¿Los sistemas asíncronos eliminan la latencia?

No. Pueden reducir el tiempo hasta el acknowledgement trasladando trabajo después de la respuesta, pero siguen existiendo latencia de finalización, colas, retries y recuperación de fallos.

¿P99 siempre es más útil que P95?

No. P99 es más sensible a la cola, pero puede ser más ruidoso con bajo volumen y más costoso de optimizar. Elige el percentil que represente el riesgo para usuario y negocio, y usa otros percentiles para comprender la distribución.

Conclusión

La latencia no es una propiedad que pueda asignarse a un servicio y optimizarse de forma aislada. Es la consecuencia temporal del recorrido completo: establecimiento de conexiones, colas, adquisición de recursos, procesamiento, llamadas downstream, fan-out, retries y entrega de la respuesta.

El método accionable es:

  1. definir un objetivo end-to-end por percentil y un límite de medición;
  2. preservar margen mediante un presupuesto de latencia;
  3. medir distribuciones en lugar de promedios;
  4. identificar el camino crítico de reloj;
  5. separar cómputo de espera;
  6. cambiar la capa propietaria del retraso dominante;
  7. validar el mismo percentil visible para el usuario bajo carga representativa.

Una plataforma con CPU disponible y pocos errores puede seguir siendo operacionalmente lenta. La evidencia que resuelve esa tensión no es otro dashboard agregado. Es un recorrido coherente desde el percentil afectado hasta la espera, dependencia, cola, conexión o política de reintentos que consumió el presupuesto.

Fuentes técnicas

Jorel del Portal

Jorel del Portal

Jorel del Portal es ingeniero de sistemas especializado en arquitectura, integración, resiliencia y observabilidad de plataformas críticas. Diseña sistemas, construye productos y documenta decisiones reales de ingeniería.