La latencia P99 es el tiempo de respuesta que supera el 99 % de las solicitudes. Si el P99 de una API es de 400 milisegundos, 99 de cada cien solicitudes vuelven en 400 ms o menos y una tarda más. P95 es la misma idea al 95 %: una de cada veinte solicitudes es más lenta. Ambos describen la cola de la distribución, las solicitudes lentas que una media disimula.
La cola importa más de lo que su tamaño sugiere. Quien hace una sola solicitud rara vez la nota. Quien habla con un agente de voz durante veinte turnos probablemente sí. Esta guía explica cómo funcionan los percentiles, cómo calcularlos, los errores que los hacen mentir y qué significan para la IA de voz en tiempo real.
P50, P95 y P99 de un vistazo
| Percentil | Qué indica | Solicitudes más lentas |
|---|---|---|
| P50 | La mediana, una solicitud típica | 1 de cada 2 |
| P90 | El comienzo de la cola lenta | 1 de cada 10 |
| P95 | El objetivo habitual en paneles y SLO | 1 de cada 20 |
| P99 | Ralentizaciones raras: pausas, reintentos, colas | 1 de cada 100 |
| P99.9 | Casos aislados que solo aparecen con mucho volumen | 1 de cada 1.000 |
Los percentiles altos necesitan más muestras para significar algo. Un P99 calculado con 100 solicitudes depende de una sola. Usa al menos unos cientos de muestras para el P95 y unos miles para el P99, y muestra el número de muestras junto al resultado.
Por qué la media oculta la cola
Toma 100 solicitudes. 94 terminan en 200 ms y 6 tardan dos segundos. La media es 308 ms, un tiempo que no tardó ninguna solicitud. La mediana es 200 ms, que parece estupendo. El P95 y el P99 son 2.000 ms, que es lo que vieron seis de tus usuarios.
Las distribuciones reales de latencia son así de desiguales. La mayoría de las solicitudes van por el camino rápido y una minoría espera detrás de un disco lento, una caché fría, una pausa de recolección de basura o una cola llena. La media mezcla los dos grupos en un número que no describe a ninguno. La mediana ignora por completo el grupo lento. Los percentiles lo mantienen a la vista.
Cómo calcular P95 y P99
Ordena las mediciones de la más rápida a la más lenta y toma el valor que está al 95 % o al 99 % del recorrido. Con 200 muestras, el P95 es el valor 190 y el P99, el 198. Es el método del rango más cercano:
import math
def percentile(samples, p):
"""Nearest rank: the smallest sample with at least p% of samples at or below it."""
ordered = sorted(samples)
rank = math.ceil(p / 100 * len(ordered))
return ordered[max(rank, 1) - 1]
latencies_ms = [200] * 94 + [2000] * 6
print(percentile(latencies_ms, 50)) # 200
print(percentile(latencies_ms, 95)) # 2000
print(percentile(latencies_ms, 99)) # 2000
NumPy interpola por defecto, así que numpy.percentile puede devolver un valor entre dos muestras. Pasa method="inverted_cdf" para obtener el rango más cercano. Con pocas muestras, los dos métodos pueden diferir bastante, otra razón para indicar el número de muestras.
Los sistemas de monitorización no suelen guardar cada muestra. Cuentan las solicitudes en intervalos de latencia y estiman el percentil a partir del histograma, como hace histogram_quantile() de Prometheus. La estimación solo es tan precisa como los intervalos que la rodean, así que pon los límites cerca de las latencias que te importan.
Tres errores que hacen mentir a los percentiles
Promediar percentiles. Supón que un servidor atiende 900 solicitudes, todas en 200 ms, y otro atiende 100, diez de las cuales tardan un segundo. Los P95 son 200 ms y 1.000 ms, y su media es 600 ms. El P95 real de las 1.000 solicitudes es 200 ms. La documentación de Prometheus lo dice: los cuantiles calculados por separado no se pueden agregar. Combina los histogramas o las muestras y calcula después.
Sumar los percentiles de cada etapa. Un agente de voz encadena reconocimiento de voz, un modelo de lenguaje y texto a voz. Supón que el reconocimiento siempre tarda 300 ms, el LLM tarda 500 ms pero 1.500 ms en una de cada diez llamadas, y el TTS tarda 150 ms pero 600 ms en una de cada diez. Sumar los P95 de cada etapa da 2.400 ms. El P95 real del turno completo es 1.950 ms, porque los dos casos lentos rara vez coinciden en el mismo turno. Mide el tiempo de extremo a extremo directamente en lugar de estimarlo por partes.
Medir con un cliente que espera. Un generador de carga que envía la siguiente solicitud solo cuando vuelve la anterior envía menos solicitudes justo cuando el servidor va lento, así que los periodos lentos quedan infrarrepresentados. Gil Tene lo llama omisión coordinada, y su generador de carga wrk2 existe para evitarlo enviando a ritmo fijo. Para cifras de producción, mide el tráfico real y no un cliente de prueba.
Por qué la cola decide cómo se siente un agente de voz
La conversación funciona con tiempos muy ajustados. Una revisión de la investigación sobre la toma de turnos de Levinson y Torreira concluye que las pausas entre turnos son del orden de 200 ms. En un estudio de llamadas telefónicas, Kendrick y Torreira observaron que las respuestas tras pausas de más de unos 700 ms eran sobre todo rechazos y otras respuestas no preferidas, y que incluso pausas de más de unos 300 ms hacían menos probable una aceptación sin matices. Quien escucha interpreta las pausas, así que un agente que se queda callado 900 ms puede sonar reacio, no solo lento.
Ahora multiplica por turnos. Si cada turno tiene, de forma independiente, un 5 % de probabilidad de superar el P95, una llamada de 20 turnos tiene un 64 % de probabilidad de toparse con al menos uno (1 − 0,95²⁰). Incluso el P99 aparece en cerca del 18 % de las llamadas de 20 turnos. La mediana describe un turno típico; la cola describe una llamada típica. Jeff Dean y Luiz André Barroso, de Google, plantearon lo mismo para servicios grandes en The Tail at Scale: cuando una acción del usuario se reparte en muchas solicitudes, las respuestas lentas poco frecuentes se vuelven habituales.
Qué medir en una cadena de voz
Mide lo que oye quien llama. En un agente de voz, es el tiempo desde que la persona termina de hablar hasta la primera muestra audible de la respuesta, registrado en su lado de la línea. Después divídelo por etapas para saber de dónde viene la cola:
| Etapa | Qué medir | Causas habituales de la cola |
|---|---|---|
| Detección de turno | Del fin de la voz a que el turno se da por terminado | Dudas, ruido de fondo, pausas largas |
| Voz a texto | Del fin del turno a la transcripción final | Turnos largos, jitter de red |
| LLM y herramientas | De la transcripción al primer token, con herramientas | Herramientas lentas, prompts largos, colas del proveedor |
| Texto a voz | Del primer texto enviado al primer audio audible | Conexiones nuevas, primeras frases largas |
| Red y teléfono | Del audio saliendo de tu servidor a quien llama | Enrutamiento del operador, búferes de jitter |
El tiempo hasta el primer audio (TTFA) es la cifra de TTS que hay que vigilar, porque un modelo en streaming empieza a sonar antes de que la frase esté completa. El silencio inicial también cuenta: un fragmento que empieza con 300 ms de silencio son 300 ms más de espera. El script de abajo mide los primeros bytes, así que revisa el silencio inicial de tu audio por separado.
Este script mide percentiles de TTFA para el texto a voz Sonic de Cartesia. Programa 205 solicitudes con medio segundo de separación, descarta las cinco primeras y mide cada una desde su hora programada hasta los primeros bytes de audio. Medir desde la hora programada, y no desde el envío, hace que una respuesta lenta que retrasa la siguiente solicitud aparezca en las cifras, lo que evita la omisión coordinada descrita arriba:
import math
import os
import time
from cartesia import Cartesia
def percentile(samples, p):
"""Nearest rank: the smallest sample with at least p% of samples at or below it."""
ordered = sorted(samples)
rank = math.ceil(p / 100 * len(ordered))
return ordered[max(rank, 1) - 1]
# max_retries=0: a retried request would hide a failure inside a slow sample.
client = Cartesia(api_key=os.environ["CARTESIA_API_KEY"], max_retries=0)
interval = 0.5 # seconds between scheduled requests
ttfa_ms = []
failures = 0
first = time.perf_counter() + interval
for i in range(205):
# Each request has a fixed start time. If a slow response makes us late,
# the wait counts against latency instead of quietly thinning the sample.
scheduled = first + i * interval
time.sleep(max(0.0, scheduled - time.perf_counter()))
got_audio = False
try:
with client.tts.with_streaming_response.generate(
model_id="sonic-3.6",
transcript="Your order shipped this morning and should arrive on Thursday.",
voice="6ccbfb76-1fc6-48f7-b71d-91ac6298247b",
output_format={"container": "raw", "encoding": "pcm_s16le", "sample_rate": 16000},
language="en",
) as response:
for chunk in response.iter_bytes():
if chunk:
got_audio = True
if i >= 5: # the first requests pay for connection setup
ttfa_ms.append((time.perf_counter() - scheduled) * 1000)
break
except Exception:
pass
if not got_audio:
failures += 1
print(f"{len(ttfa_ms)} timed requests, {failures} failed or returned no audio")
if ttfa_ms:
for p in (50, 90, 95, 99):
print(f"p{p}: {percentile(ttfa_ms, p):.0f} ms")
print(f"max: {max(ttfa_ms):.0f} ms")
Instala el SDK con pip install cartesia y define CARTESIA_API_KEY desde el panel. Ejecútalo desde la región donde corren tus servidores y a la hora de más tráfico, porque un portátil con el wifi de casa mide el wifi. El SDK reintenta dos veces por defecto las solicitudes fallidas, lo que mezclaría un fallo y su reintento en una sola muestra lenta, así que el script desactiva los reintentos y cuenta aparte los fallos, incluidas las respuestas sin audio. No los quites del informe: una solicitud que nunca respondió es la peor latencia de todas. Para un agente en vivo, mide la ruta por WebSocket que de verdad usas, porque mantiene una conexión abierta entre turnos.
Qué muestran los benchmarks públicos
Coval ejecuta cada 30 minutos benchmarks independientes de texto a voz, voz a texto y voz a voz contra API públicas, y publica medianas, percentiles y número de muestras. Su metodología incluye el silencio inicial en el TTFA y excluye el establecimiento de conexiones.
En su tabla de texto a voz de 30 días, consultada el 15 de octubre de 2026, la distancia entre mediana y P95 variaba mucho entre 33 modelos con al menos 260 muestras cada uno. Para el modelo típico, el P95 era 1,38 veces la mediana. En los extremos, el P95 de un modelo era 1,1 veces su mediana y el de otro, más de siete veces: 624 ms en lo típico y 4.751 ms en una de cada veinte solicitudes.
La lección es la del principio de esta guía: dos modelos con medianas parecidas pueden sentirse muy distintos en una llamada. Compara los P95, con el número de muestras, medidos como los viven tus usuarios.
Cómo reducir la latencia de cola
- Mantén las conexiones abiertas. Cada nueva solicitud HTTPS vuelve a pagar el establecimiento de TCP y TLS, y la documentación de Cartesia señala que ese coste suele ser del mismo orden que el tiempo hasta el primer byte de audio. Un WebSocket abierto durante toda la llamada lo paga una vez.
- Guarda en caché lo que se repite. Los saludos, los mensajes de espera y las despedidas no necesitan generarse de nuevo en cada llamada. Guárdalos como audio sin procesar e intercálalos en el flujo en vivo.
- Empieza a hablar antes. Envía los tokens del LLM al texto a voz a medida que llegan en lugar de esperar a un párrafo completo.
- Pon un plazo a las herramientas. Una llamada a una herramienta que tarda dos segundos añade dos segundos al turno, cada vez. Fija un tiempo límite y haz que el agente diga lo que está haciendo mientras espera.
- Cubre las solicitudes lentas. The Tail at Scale describe enviar una solicitud de respaldo cuando la primera lleva más tiempo que el P95 habitual y usar la que responda antes. Esperar hasta el P95 limita la carga extra a cerca de un 5 %. Hazlo solo con solicitudes que se puedan enviar dos veces sin riesgo, como volver a generar el mismo audio, nunca con una herramienta que escribe datos.
- Ejecuta los modelos cerca de la llamada. Si tu cola viene de la distancia de red o de infraestructura compartida, el despliegue on-premise pone los modelos junto a tu telefonía.
Si prefieres no montar ni ajustar la cadena tú mismo, Cartesia Managed Agents ejecuta la detección de turnos, la voz a texto de Ink, el LLM y Sonic sobre un número de teléfono, y puedes crear uno en el playground y llamarlo. Si tu propia cadena va lenta, la solución suele estar en la etapa que señalen tus mediciones, y el script de arriba es el punto de partida.