Testing de Carga de APIs con k6 y Aserciones Basadas en
Como escribir y ejecutar tests de carga con k6 para medir rendimiento de APIs, validar SLOs e identificar cuellos de botella antes del despliegue a produccion
k6 es una herramienta moderna de testing de carga construida para desarrolladores. Usa JavaScript para scripting de tests y proporciona metricas integradas, aserciones de umbrales y escenarios modulares que te ayudan a validar requerimientos de rendimiento antes de que el codigo llegue a produccion.
Cuando Usar Esto
- Necesitas verificar que las APIs cumplen SLOs de tiempo de respuesta y throughput. Consulta Health Check Endpoint para monitoreo de APIs.
- Quieres simular patrones de trafico de usuarios realistas. Consulta Load Testing para estrategias de carga.
- El testing de regresion debe detectar degradacion de rendimiento en CI/CD. Consulta CI/CD Pipeline para integración continua.
Requisitos Previos
- k6 instalado (
brew install k6o descargar desde k6.io) - Un endpoint de API ejecutandose para testear
Solucion
1. Script Basico de Test de Carga
// load-tests/basic.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp up
{ duration: '5m', target: 100 }, // Estado estable
{ duration: '2m', target: 200 }, // Spike
{ duration: '5m', target: 200 }, // Carga sostenida
{ duration: '2m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% bajo 500ms
http_req_failed: ['rate<0.01'], // Tasa de error bajo 1%
},
};
export default function () {
const response = http.get('https://api.example.com/products');
check(response, {
'status es 200': (r) => r.status === 200,
'tiempo de respuesta < 500ms': (r) => r.timings.duration < 500,
'tiene array de productos': (r) => r.json().length > 0,
});
sleep(1);
}
2. Testing de API Autenticada
// load-tests/authenticated.js
import http from 'k6/http';
import { check } from 'k6';
const BASE_URL = __ENV.BASE_URL || 'https://api.example.com';
const AUTH_TOKEN = __ENV.AUTH_TOKEN;
export const options = {
vus: 50,
duration: '10m',
};
export default function () {
const params = {
headers: {
Authorization: `Bearer ${AUTH_TOKEN}`,
'Content-Type': 'application/json',
},
};
// Simular un flujo de usuario
const cart = http.post(`${BASE_URL}/cart`, JSON.stringify({ items: [1, 2, 3] }), params);
check(cart, { 'carrito creado': (r) => r.status === 201 });
const checkout = http.post(`${BASE_URL}/checkout`, JSON.stringify({ cartId: cart.json('id') }), params);
check(checkout, {
'checkout exitoso': (r) => r.status === 200,
'orden confirmada': (r) => r.json('status') === 'confirmed',
});
}
3. Ejecutar Tests e Interpretar Resultados
# Ejecutar test de carga basico
k6 run load-tests/basic.js
# Ejecutar con variables de entorno
k6 run --env BASE_URL=https://staging.example.com --env AUTH_TOKEN=token123 load-tests/authenticated.js
# Output a InfluxDB para dashboards de Grafana
k6 run --out influxdb=http://localhost:8086/k6 load-tests/basic.js
# Ejecucion en cloud para carga distribuida
k6 cloud run load-tests/basic.js
4. Smoke Test para CI/CD
// load-tests/smoke.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
vus: 1,
iterations: 1,
thresholds: {
http_req_duration: ['max<2000'],
http_req_failed: ['rate===0'],
},
};
export default function () {
const endpoints = [
'/health',
'/products',
'/users/me',
];
for (const endpoint of endpoints) {
const res = http.get(`https://api.example.com${endpoint}`);
check(res, {
[`${endpoint} es 200`]: (r) => r.status === 200,
});
}
}
Como Funciona
- Virtual Users (VUs) simulan clientes concurrentes haciendo peticiones
- Stages definen patrones de ramp-up, carga sostenida y ramp-down
- Thresholds aseguran que metricas cumplan SLOs; thresholds fallidos salen con estado no-cero
- Checks validan correccion funcional bajo carga
Consideraciones de Produccion
- Ejecuta smoke tests en cada pull request para detectar regresiones basicas
- Programa soak tests (ejecuciones de horas) para encontrar memory leaks
- Usa ambientes separados para testing de carga; nunca testees produccion directamente
- Correlaciona metricas de k6 con herramientas APM (Datadog, New Relic) para analisis de root cause
Errores Comunes
- Testear desde una sola maquina que se convierte en cuello de botella
- No calentar la aplicacion antes de medir rendimiento de estado estable
- Usar
sleep()con intervalos aleatorios que no coinciden con think time de usuarios reales
Manejo de Errores y Recuperacion
- Fallos de compression: cuando Brotli compression falla, sirve uncompressed content como fallback. Setea compression quality basado en CPU availability.
- Fallos de CDN origin: cuando CDN no puede alcanzar origin, sirve stale content. Setea appropriate TTLs.
- Connection pool exhaustion: cuando todas las connections estan in use, requests queuean o fallan. Setea max pool size basado en database capacity.
- Fallos de lazy loading intersection observer: cuando Intersection Observer falla, content nunca loads.
- Fallos de load test scripts: cuando k6 scripts fallan, test results son invalid. Valida test scripts antes de execution. Usa version control para test scripts.
- Fallos de code splitting: cuando dynamic imports fallan, components no loadean. Usa prefetch para critical chunks.
Performance y Escalabilidad
- Tuning de compression level: Brotli level 4 para dynamic content. Brotli level 11 para static assets. Gzip level 6 como fallback.
- Optimizacion de CDN cache hit ratio: maximiza cache hit ratio para reducir origin load. Setea appropriate Cache-Control headers. Purga cache en content updates.
- Sizing de connection pool: dimensiona pools basado en concurrent request volume. Empieza con 10 connections por pool. Incrementa pool size si wait time excede 100ms. Decrementa si connections estan idle.
- Tuning de lazy loading threshold: setea root margin para early loading. Usa 400px para heavy components. Ajusta threshold basado en device performance.
- Patrones de load test ramp: Empieza con 10 users. Rampea a 100 over 2 minutes. Hold por 5 minutes. Rampea a peak. Hold por 10 minutes. Ramp down.
- Optimizacion de bundle size: Splitea vendor y app code. Analiza bundle con webpack-bundle-analyzer. Setea performance budgets.
Consideraciones de Seguridad
- HTTPS y compression: habilita compression solo sobre HTTPS para prevenir BREACH attacks. No comprimas sensitive responses con user-controlled input. o-transform header para content ya compressed. Monitorea compression-related vulnerabilities. Documenta security configuration. Testea con security scanners. Revisa security trimestralmente
- Seguridad de CDN: secura CDN con proper access controls. Habilita DDoS protection.
- Seguridad de connection pool: Setea connection timeout para prevenir slow-loris attacks. Rota database credentials.
- Content Security Policy para lazy loading: setea CSP headers para permitir lazy-loaded resources.
Deployment y CI/CD
- Performance testing en CI: corre performance tests en cada PR. Usa k6 para load testing. Setea performance budgets. Failea builds en budget violations.
- Deployment progresivo para performance changes: deploya performance changes gradualmente. Roll back en regression.
- Bundle analysis en CI: analiza bundle size en cada build. Setea size budgets por chunk.
Testing y Quality Assurance
- Performance regression testing: corre performance tests en cada release.
- Best practices de load testing: Rampea up gradualmente. Usa production-like data volumes.
- CDN cache testing: verifica que cache headers esten seteados correctamente. Verifica stale content serving. Testea con query parameters.
Herramientas y Plataformas
- WebPageTest: herramienta detailed de web performance testing. Waterfall view de resource loading. Filmstrip view de visual progress. Setea custom connectivity profiles.
- Lighthouse: herramienta de Google para web performance auditing. Scorea performance, accessibility, SEO y best practices. Setea performance budget basado en Lighthouse scores.
- k6: herramienta modern de load testing por Grafana. Soporte para HTTP, gRPC, WebSocket. Thresholds para pass/fail. Cloud execution option. Integration con Grafana. Crea reusable test scenarios.
- webpack-bundle-analyzer: visualiza bundle composition. Encuentra duplicate modules. Setea size alerts.
- Cloudflare CDN: CDN global con edge caching. Workers para edge compute. Cache rules y page rules. Real-time analytics. DDoS protection incluido.
- Fastly CDN: CDN con instant purge. VCL para edge configuration. Real-time logging. Image optimization.
Pitfalls Comunes y Anti-Patrones
- Over-compression: comprimir content ya compressed wastea CPU. No comprimas images, videos o pre-compressed assets. Setea gzip_types y rotli_types cuidadosamente.
- Miconfiguracion de CDN: incorrect cache headers causan poor hit ratio. No cachees personalized content. Setea appropriate TTLs.
- Connection pool over-sizing: demasiadas connections wastean database resources. Setea max pool size basado en database capacity.
- Lazy loading everything: lazy loading above-the-fold content perjudica LCP. Loadea critical content eagerly. Usa etchpriority=“high” para LCP elements.
- Load testing sin think time: load testing sin think time crea unrealistic load. Agrega think time entre requests. Simula real user behavior.
- Code splitting demasiado granular: demasiados small chunks causan excessive network requests. Groupa related components en chunks. Setea minimum chunk size.
Resumen de Best Practices
- Setea performance budgets: define budgets para key metrics. LCP under 2. 5 segundos. FID under 100ms. CLS under 0. 1. Bundle size under 200KB. Failea builds en violations.
- Monitorea Core Web Vitals: Usa synthetic monitoring para lab data. Setea alerts en metric degradation.
- Optimiza critical rendering path: Inlinea critical CSS. Deferea non-critical JavaScript.
- Usa progressive enhancement: builda core functionality primero. Enhancea con JavaScript. Usa server-side rendering.
Optimizacion de Costos
- Gestion de costos de CDN: Setea appropriate TTLs para maximizar cache hits. Usa compression para reducir bandwidth.
- Costos de CPU de compression: Pre-comprime static assets en build time.
- Costos de resources de connection pool: Cierra unused connections.
- Costos de load testing infrastructure: Programa tests durante off-peak. Usa cloud-native load testing.
Guia de Troubleshooting
- Slow page load: diagnostica con WebPageTest. Minifica CSS y JavaScript.
- High CDN origin requests: Verifica cache key configuration.
- Connection pool timeouts: chequea pool size. Incrementa pool size si needed.
- Poor load test results: Verifica test environment. Scalea infrastructure.
Monitoring y Alerting
- Estrategia de performance monitoring: Setea thresholds para alerts. Usa synthetic monitoring para lab data.
- Configuracion de alerts para performance: setea alerts en metric degradation. LCP above 2. 5 segundos. Error rate above 1%. Response time above 500ms. Reduce alert noise.
- Diseno de dashboards para performance: crea dashboards para diferentes audiences. Executive dashboard para high-level metrics. Engineering dashboard para detailed metrics. Operations dashboard para real-time monitoring.
- Deteccion de performance regression: automatiza regression detection.
Patrones Avanzados
- Edge computing para performance: mueve computation al edge. Reduce latency para global users. Cachea dynamic content en edge.
- Optimizacion de resource hints: Usa preload para key resources. Usa dns-prefetch para external domains.
- Pipeline de image optimization: Usa modern formats como WebP y AVIF.
Estrategias de Migracion
- Migracion de gzip a Brotli: habilita Brotli junto a gzip para gradual migration. Roll out progresivamente.
- Migracion a un nuevo CDN: corre ambos CDNs en paralelo durante migration. Verifica SSL certificates. Switchea DNS gradualmente.
- Migracion de connection pools: migra pool configuration gradualmente. Roll out a un service a la vez. Completa migration despues de validation.
Compliance y Governance
- Performance SLAs: define performance SLAs para critical endpoints. API response time under 200ms. Page load time under 3 segundos.
- Performance reporting: genera weekly performance reports.
Referencia Rápida
- Comando principal: ejecuta la solución base del artículo y verifica el resultado esperado.
- Validación: confirma que los tests pasan y que las métricas clave no se degradaron.
- Rollback: si algo falla, revierte el cambio y consulta la sección de Troubleshooting.
Lectura Adicional
- Documentación oficial: consulta la referencia actualizada del framework o herramienta utilizada.
- Guías relacionadas: explora las guías de benchmarks y testing para profundizar.
- Patrones complementarios: revisa los patrones de diseño aplicables a tu stack tecnológico.
- Postmortems públicos: estudia incidentes reales de equipos que enfrentaron problemas similares en producción.
Notas de Producción
- Despliega gradualmente usando canary o blue-green para detectar regresiones temprano.
- Configura alertas para errores, latencia p99 y tasa de fallos antes de habilitar en producción.
- Documenta el rollback en el runbook; prueba el procedimiento en staging al menos una vez por trimestre.
- Revisa logs estructurados con correlation IDs para trazar requests end-to-end en incidentes.
Puntos Clave
- Aplica testing de carga de apis con k6 y aserciones basadas en cuando necesites una solución práctica para tu caso de uso.
- Monitorea el rendimiento después de implementar; mide latencia, errores y uso de recursos antes y después.
- Revisa la sección de Troubleshooting ante errores comunes; la mayoría tienen causa raíz documentada con solución.
- Mantén dependencias actualizadas y ejecuta tests en CI para prevenir regresiones en producción.
Errores Comunes en Producción
- Copiar el ejemplo sin adaptarlo a volúmenes y modos de fallo reales.
- Saltar tests de carga e inyección de errores antes del primer despliegue productivo.
- Codificar valores fijos que deberían ser configurables por entorno.
- Olvidar agregar logging y monitoreo en cada paso.
- Desplegar sin plan de rollback ni estrategia de backup probada.
- Asumir que el ejemplo mínimo escalará sin agregar caché o procesamiento por lotes.
- No documentar la versión y configuración usadas en producción.
- Dejar la receta sin cambios cuando evolucionan las dependencias o la escala.
Preguntas frecuentes
Cuantos VUs necesito para simular 10,000 usuarios reales?
Depende de la frecuencia de peticiones. Si cada usuario hace una peticion cada 30 segundos, 50-100 VUs pueden simular 10,000 usuarios.
Puede k6 testear conexiones WebSocket?
Si, a traves del modulo experimental k6/ws, aunque herramientas dedicadas de WebSocket pueden ser mas apropiadas.
Como manejo datos en vivo en tests de carga?
Usa papaparse para leer archivos CSV o genera datos randomizados con funciones random integradas.
Recursos Relacionados
Realizar Load Testing en APIs
Cómo simular tráfico realista, medir tiempos de respuesta e identificar cuellos de botella usando k6 y JMeter para APIs y servicios web.
RecipeTests de Integración con Dependencias Reales
Cómo probar múltiples componentes trabajando juntos usando bases de datos reales, clientes HTTP y colas de mensajes en Python, JavaScript y Java.
GuideGuía de Estrategia de Testing de Software
Una guía práctica para construir una estrategia de testing en capas con tests unitarios, de integración, de contrato y end-to-end que tu equipo realmente mantendrá.
RecipeAPI Mocking para Testing
Construye tests confiables simulando APIs externas con WireMock, MockServer y MSW para eliminar inestabilidad y probar casos límite.
DocPlantilla de Estrategia de Testing de API
Una plantilla para planificar tests de contrato, integración y carga para APIs.
DocPlantilla de Plan de Pruebas de Carga
Plantilla rellenable de plan de pruebas de carga: escenarios, perfiles de ramp-up, umbrales de éxito, monitoreo y scripts listos para k6, JMeter y Locust.