---
title: "SSE y long-polling bajo carga: patrón práctico de prueba con k6"
description: "Prueba en carga SSE y long-polling: streams concurrentes, timeouts idle de proxy y patrones k6—MDN, HTTP/1.1 y comparación con WebSockets."
publishDate: "2026-06-29"
draft: false
keyword: "server sent events pruebas carga"
intent: "MOFU"
cta: "Usa Performate para convertir este playbook en escenarios k6 ejecutables, umbrales y reportes compartibles sin perder días en código de integración."
tags: ["k6", "pruebas-de-carga", "rendimiento-api", "sse"]
translationOf: sse-long-polling-load-testing-k6
---

Los dashboards que usan **SSE** o **long-polling** y se cuelgan bajo streams concurrentes fallan de forma distinta a las ráfagas REST: dominan los timeouts idle del proxy, los topes de conexión y el buffer bloat ([MDN SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events), [HTTP keep-alive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive)). Un pico de GETs cortos no dice nada sobre diez mil streams abiertos detrás del mismo balanceador.

k6 puede abrir conexiones HTTP de larga duración; hay que modelar **conteo de streams concurrentes** y **duración de requests largos**, no solo RPS de GETs de menos de un segundo. En esta guía verás modos de fallo, un patrón de VUs concurrentes con timeouts extendidos y cuándo comparar con [patrones de carga WebSocket](/es/blog/pruebas-carga-k6-websocket-conexiones).

## Modos de fallo bajo streams concurrentes

Las UIs orientadas a eventos y los feeds en vivo estresan infraestructura que los benchmarks REST no tocan:

- **El proxy cierra conexiones idle** a los 60 s mientras el servidor cree que el stream sigue abierto: la tormenta de reconexiones amplifica la carga.
- **Agotamiento de descriptores de archivo** en gateways e ingress: los errores parecen 502 aleatorios.
- **Fan-out:** un evento del servidor dispara N polls de clientes o fetches downstream—multiplica la carga más allá del conteo de VUs de k6.
- **Buffer bloat** en consumidores lentos: la memoria sube en intermediarios mientras k6 sigue recibiendo 200.
- **Límites de reutilización de conexión HTTP/1.1** por host—el conteo de VUs no es igual al de pestañas del navegador, pero la dirección es similar.

El long-polling difiere ligeramente: GETs largos repetidos por ciclo de VU en lugar de un stream infinitamente abierto—modela ambos si el producto usa patrones híbridos.

### SSE vs WebSocket vs long-poll

| Patrón | Modelo de carga | Nota k6 |
|:---|:---|:---|
| SSE | Muchos GET abiertos concurrentes | `Accept: text/event-stream`, timeout largo |
| Long-poll | GET largos repetidos por VU | Bucle más corto con timeout cerca del hold del servidor |
| WebSocket | Frames bidireccionales | Ver [guía WebSocket k6](/es/blog/pruebas-carga-k6-websocket-conexiones); casos avanzados pueden requerir xk6 |

## Patrón k6: GET largo con timeout extendido

**Ilustrativo—no listo para producción.** El cliente HTTP de k6 lee el body completo por defecto; para validación de parser SSE de grado producción considera herramientas complementarias o extensiones xk6. Este patrón sigue estresando tablas de conexión y timeouts de proxy.

**Qué demuestra este ejemplo:**

- `constant-vus` equivale a streams abiertos concurrentes—ajusta `STREAM_VUS` a viewers en vivo esperados, no a RPS REST.
- `timeout` extendido en `http.get`—120 s de ejemplo; alinea con hold de long-poll del servidor + margen.
- Header `Accept: text/event-stream`—misma ruta que usan los navegadores.
- Tags `protocol:sse` separan umbrales de escenarios REST en suites mixtas.

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

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

export const options = {
  scenarios: {
    sse_clients: {
      executor: 'constant-vus',
      vus: Number(__ENV.STREAM_VUS || 100),
      duration: '5m',
      tags: { protocol: 'sse' },
    },
    rest_baseline: {
      executor: 'constant-arrival-rate',
      rate: 20,
      timeUnit: '1s',
      duration: '5m',
      tags: { protocol: 'rest' },
    },
  },
  thresholds: {
    http_req_failed: ['rate<0.02'],
    'http_req_duration{protocol:sse}': ['p(95)<5000'],
    'http_req_duration{protocol:rest}': ['p(95)<400'],
  },
};

export default function () {
  const res = http.get(`${BASE}/events/stream`, {
    headers: { Accept: 'text/event-stream' },
    timeout: '120s',
    tags: { route: 'stream', protocol: 'sse' },
  });
  check(res, { connected: (r) => r.status === 200 });
  sleep(Number(__ENV.RECONNECT_SEC || 5));
}
```

**Patrones que funcionan**

- **Rampa de VUs por stages**—encuentra la rodilla del límite de conexiones antes del conteo completo de viewers.
- **Alinear timeouts idle de proxy/load balancer** en el runbook—si el proxy mata a 60 s, no uses timeout de 120 s sin esperar churn de reconexión.
- **Monitorizar FDs abiertos en el gateway** durante la prueba—aborta si la pendiente es lineal.
- **Escenarios REST y SSE separados**—no mezcles umbrales; los modos de fallo difieren.

**Anti-patrones a evitar**

- Medir solo health REST corto mientras el dolor en producción son streams concurrentes.
- Poner VUs igual a números de RPS REST—los streams son conexiones concurrentes, no req/s.
- Ignorar tormentas de reconexión tras timeout de proxy—la segunda ola puede superar la primera.
- Correr el conteo completo de viewers en producción sin control de cambios.

**Pro tip (comando de ejemplo):** rampa VUs de stream para encontrar la rodilla.

```bash
k6 run sse-load.js --env STREAM_VUS=50 --duration 3m --tag protocol=sse
```

**Qué demuestra este comando:** pruebas incrementales de VUs en escritorio localizan límites de FD del gateway antes de programar el ensayo completo de 5k streams con platform on-call.

## Marco de decisión: patrón vs modelo de carga

| Patrón | Modelo de carga | Métrica principal |
|:---|:---|:---|
| SSE push | Muchos GET abiertos concurrentes | VUs concurrentes + errores de stream |
| Long-poll | GET largos repetidos por VU | Tiempo de ciclo + tasa de timeout |
| REST + SSE mixto | Escenarios separados | No mezclar `p95` |
| Fan-out backend | Mock downstream o monitor | Profundidad de broker/cola si aplica |

**Corre escenario REST baseline en paralelo**—demuestra que la API sigue sana mientras los streams están abiertos. Algunos equipos solo rompen REST cuando la tabla de conexiones está llena.

## Observabilidad y checklist pre-corrida

- [ ] Timeouts idle de proxy/load balancer documentados en el runbook.
- [ ] Monitorizar FDs abiertos y conteo de conexiones en el gateway durante la prueba.
- [ ] Abortar si la tasa de error sube en los primeros 10 minutos—no quemar staging ciegamente.
- [ ] Coordinar con el equipo de red—ingress compartido puede afectar servicios no relacionados.
- [ ] Anotar limitaciones HTTP de k6 para parsing de eventos—documentar si la prueba es solo conexión vs validación de payload.
- [ ] Comparar resultados con la ruta [WebSocket](/es/blog/pruebas-carga-k6-websocket-conexiones) si el producto evalúa migración.

## Cómo Performate apoya pruebas SSE/long-poll

Abajo hay un **ejemplo concreto de flujo** para carga del endpoint de stream—adapta conteos de VU a tu pico de viewers concurrentes.

**Ejemplo: rampa de VUs de stream con export para networking**

1. **Importa** el endpoint de stream desde Postman—headers incluyendo `Accept`. *Problema resuelto:* la misma ruta que QA usa funcionalmente se convierte en objetivo de carga.
2. **Configura** escenario VU + timeout largo en la UI—120 s o según runbook. *Problema resuelto:* evita editar strings de timeout a mano en cada iteración.
3. **Corre** rampa por stages en VUs—50, 100, 200 con tripwires de abort. *Problema resuelto:* encuentra la rodilla antes del ensayo a escala completa.
4. **Exporta** timeouts y errores de conexión filtrados por `protocol:sse`. *Problema resuelto:* el equipo de plataforma recibe desglose por código de estado, no un genérico «lento».
5. **Comparte** el export con platform—captura de FDs con el mismo timestamp. *Problema resuelto:* el ticket de capacidad enlaza la prueba de app con evidencia de infra.
6. **Guarda** plantilla para release—retag `protocol:sse` por evento. *Problema resuelto:* repite antes de cada lanzamiento de dashboard en vivo.

Ese flujo encaja con el `cta` de este post: escenarios de conexión larga ejecutables sin semanas de glue code.

## Cierre

La carga SSE/long-poll es un problema de **presupuesto de conexiones**: rampa streams concurrentes, alinea timeouts con reglas de proxy y nunca mezcles umbrales SSE con baselines REST.

Programa una rampa de VUs esta semana en staging, observa métricas de conexión del gateway durante la corrida y anota el conteo de VU donde empiezan los errores—ese número pertenece al checklist de lanzamiento.

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