---
title: "Latencia P95 vs P99: qué importa de verdad para la confiabilidad de APIs"
description: "Cómo los percentiles de latencia resumen riesgo de cola, cuándo p95 gana a p99 para gates y cómo k6 reporta http_req_duration para releases honestos."
publishDate: "2026-05-15"
draft: false
keyword: "p95 vs p99 latencia"
intent: "MOFU"
cta: "Sigue umbrales p95 y p99 en Performate y compara regresiones antes del release."
tags: ["latencia", "p95", "p99", "rendimiento-api"]
translationOf: p95-vs-p99-latency
---

El release muestra latencia media de checkout en 180 ms—producto aplaude—pero soporte sigue recibiendo tickets de «pago colgado» en el 1 % peor de sesiones.

El **promedio** oculta colas. **p95** marca la latencia por debajo de la cual cae el 95 % de observaciones; **p99** marca el 1 % más lento por encima de p95. Para cargas HTTP, k6 registra `http_req_duration` y stats que puedes umbralizar ([métricas](https://k6.io/docs/using-k6/metrics/), [thresholds](https://k6.io/docs/using-k6/thresholds/)).

En esta guía verás por qué equipos gatean en p95, cuándo p99 (o max) merece atención, cómo configurar umbrales k6 por ruta, errores que invalidan argumentos de percentiles y cómo Performate ayuda a comparar regresiones entre releases.

Consulta también [cómo leer reportes de pruebas de carga](/es/blog/como-leer-reportes-pruebas-de-carga) y [cuántos usuarios virtuales](/es/blog/cuantos-usuarios-virtuarios-k6): los percentiles solo tienen sentido con muestras suficientes y parámetros de escenario estables.

## Por qué el promedio miente en APIs bajo carga

Bajo concurrencia, latencia suele ser de cola: unos requests pasan rápido, otros esperan pool de DB, GC o locks. El promedio mezcla ambos mundos en un número cómodo para slides pero inútil para SLOs. Los percentiles responden preguntas distintas:

- **p95:** «¿Qué vio la gran mayoría, incluidos momentos moderadamente malos?»
- **p99:** «¿Qué tan mal puede ir para el 1 % peor típico?»
- **max:** outlier extremo—útil para debug, ruidoso como gate único.

Piensa en p95 como clima habitual y p99 como la tormenta que aún ocurre varias veces al día en tráfico alto.

### Por qué equipos gatean en p95

- **Señal vs ruido:** p95 se mueve cuando la experiencia típica degrada pero es menos volátil que p99 en corridas cortas.
- **Costo de ingeniería:** apretar latencia de cola suele costar esfuerzo no lineal; gates p95 detectan regresiones temprano sin perseguir cada outlier.
- **Claridad con stakeholders:** «95 % de requests más rápidos que X ms» alinea fácil con expectativas de producto ([throughput vs latencia](/es/blog/throughput-vs-latencia-stakeholders)).

## Cuándo p99 (o max) merece atención

- **Flujos safety-critical o de pago** donde lentitud rara equivale a riesgo de revenue o compliance.
- **Ventanas de muestra chicas** donde p95 se ve bien pero un servicio dependiente se estanca a veces—picos p99 lo revelan.
- **Sistemas con autoscaling o colas** donde latencia de cola predice saturación antes de que p95 se mueva.
- **Migraciones multi-versión** donde divergencia en colas importa al SLO ([versionado API bajo carga](/es/blog/pruebas-carga-versionado-api)).

Los libros SRE de Google enfatizan alinear SLIs con dolor de usuario; burn rates multi-ventana a menudo combinan señales sensibles a cola con presupuesto ([SRE workbook](https://sre.google/workbook/)).

## Implementación práctica con k6: umbrales por ruta

No uses un solo `http_req_duration` global cuando endpoints difieren en magnitud y criticidad. Umbraliza rutas etiquetadas y combina latencia con tasa de error.

**Script de ejemplo (ilustrativo—no es una prueba lista para producción).**

**Qué demuestra este ejemplo:**

- **Umbrales p95 y p99** en la misma ruta crítica.
- **Tags `route:*`** para evitar mezclar checkout con health checks.
- **Error rate** junto a latencia—«rápido pero wrong» no pasa.

```javascript
import http from 'k6/http';
import { check, sleep } from 'k6';

const BASE = __ENV.API_BASE || 'https://staging.example.com';

export const options = {
  scenarios: {
    checkout: {
      executor: 'constant-arrival-rate',
      rate: 30,
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 15,
      maxVUs: 60,
      exec: 'hitCheckout',
      tags: { route: 'checkout' },
    },
  },
  thresholds: {
    'http_req_duration{route:checkout}': ['p(95)<500', 'p(99)<1200'],
    'http_req_failed{route:checkout}': ['rate<0.01'],
    http_req_failed: ['rate<0.01'],
  },
};

export function hitCheckout() {
  const res = http.post(
    `${BASE}/checkout`,
    JSON.stringify({ sku: 'SKU-100', qty: 1 }),
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${__ENV.TOKEN}`,
      },
      tags: { route: 'checkout' },
    }
  );
  check(res, { 'checkout 2xx': (r) => r.status >= 200 && r.status < 300 });
  sleep(0.3);
}
```

**Tip pro (comando de ejemplo):**

```bash
k6 run checkout.js --summary-trend-stats="p(95),p(99),max"
```

**Qué demuestra este comando:** el summary imprime p95, p99 y max para comparar builds cuando también pasas `git_sha` vía tags o variables de entorno.

**Patrones que funcionan**

- Iteraciones altas estabilizan percentiles; micro-runs producen colas ruidosas.
- Segmenta por tags alineados a APM ([observabilidad k6](/es/blog/k6-observabilidad-metricas-tags)).
- Combina latencia con checks e `http_req_failed`—ver [ejemplos de umbrales](/es/blog/ejemplos-umbrales-k6).

**Anti-patrones a evitar**

- Comparar p95 entre corridas con distinto número de VUs o duración sin anotar drift de escenario.
- Interpretar colas en staging caliente como prod frío.
- Ignorar **coordinated omission**: si k6 bloquea más cuando el sistema está lento, existe sesgo de medición—revisa [scenarios](https://k6.io/docs/using-k6/scenarios/) para análisis estricto.

## Marco de decisión: qué percentil gatear

| Situación | Gate recomendado |
|:---|:---|
| API general, releases frecuentes | p95 por ruta + error rate |
| Checkout / pagos / auth crítica | p95 **y** p99 en rutas críticas |
| Canary post-deploy | Delta p99 vs baseline ([canary](/es/blog/releases-canary-metricas-pruebas-carga)) |
| Corridas cortas en CI | p95 conservador; p99 solo con muestra suficiente |
| Presentación a ejecutivos | p95 como headline; p99 como cola de riesgo |

**Usa p95 como gate principal si** buscas señal estable en CI y releases frecuentes.

**Añade p99 si** el dolor de usuario vive en colas raras pero repetibles en tráfico alto.

**Evita max como único gate** salvo debug—demasiado volátil para política de release.

## Errores que invalidan argumentos de percentiles

- Declarar éxito porque la media bajó mientras **p99** explotó.
- Mezclar rutas rápidas y lentas en un threshold global.
- Correr 30 segundos y debatir p99 como si fuera prod de Black Friday.
- Olvidar que [presupuesto frontend + API](/es/blog/presupuesto-rendimiento-frontend-api) exige percentiles en ambos lados.

## Cómo Performate ayuda con visibilidad de regresión

Performate ayuda a almacenar corridas comparables y resultados de umbrales para que shifts de p95/p99 aparezcan junto a metadata de release—donde hojas de cálculo y exports ad hoc suelen perder contexto.

**Ejemplo: comparar p95/p99 entre builds**

1. Define umbrales p95/p99 en el editor de escenario. *Problema resuelto:* gates explícitos, no debate a posteriori.
2. Corre baseline pre-release y candidato en el mismo workspace. *Problema resuelto:* mismos tags y executors entre comparaciones.
3. Abre vista de comparación filtrada por `route:checkout`. *Problema resuelto:* QA y backend ven divergencia de cola en un export.
4. Exporta JSON + script k6 para CI ([CI/CD](/es/blog/pruebas-de-carga-en-ci-cd)). *Problema resuelto:* historial auditables por git SHA.

## Cierre

p95 y p99 no compiten—responden preguntas distintas sobre la misma cola. Gatea en p95 para señal estable en el día a día; vigila p99 donde la lentitud rara duele de verdad al negocio.

En la próxima revisión de release, trae p95 **y** p99 de la ruta que más tickets genera—y anota si la media contaba una historia distinta.

[Try Performate free](https://performate.app) | [Book a demo](/demo) | [k6 metrics reference](https://k6.io/docs/using-k6/metrics/)
