TL;DR

  • Load testing: Medir rendimiento del sistema bajo tráfico esperado
  • Objetivo: Verificar que aplicación maneja cargas normales y pico
  • Métricas clave: Tiempo de respuesta (p95), throughput, tasa de error
  • Herramientas populares: k6 (moderno), JMeter (GUI), Gatling (Scala)
  • Mejor práctica: Testea en ambientes production-like con datos realistas
  • Cuándo ejecutar: Antes de releases, después de cambios mayores, regularmente en CI/CD

Tiempo de lectura: 12 minutos

Load testing asegura que tu aplicación puede manejar tráfico real. Sin él, descubres problemas de rendimiento por usuarios enojados — o peor, durante un momento crítico del negocio.

¿Qué es Load Testing?

Load testing mide cómo un sistema se desempeña bajo tráfico esperado de usuarios. Simula muchos usuarios concurrentes haciendo requests para verificar que la aplicación maneja la carga sin ralentizarse o fallar.

Tráfico normal:      100 users/min → Tiempo respuesta: 200ms ✓
Tráfico pico:        500 users/min → Tiempo respuesta: 350ms ✓
Sobre capacidad:    1000 users/min → Tiempo respuesta: 5000ms ✗

Load testing responde: “¿Puede nuestro sistema manejar el tráfico esperado?”

Por qué Importa Load Testing

1. Problemas de Rendimiento Son Costosos

Aplicaciones lentas cuestan dinero:

Tiempo RespuestaImpacto
Bajo 1 segundoUsuarios permanecen engaged
1-3 segundos40% abandonan
3+ segundos70%+ abandonan
10+ segundosUsuarios raramente regresan

Cada 100ms de latencia puede reducir conversión en 1%.

2. Fallos en Production Son Peores

Encontrar problemas en production significa:

  • Pérdida de ingresos durante caídas
  • Daño a reputación
  • Fixes de emergencia bajo presión
  • Potencial pérdida de datos

Load testing encuentra estos problemas antes que los usuarios.

3. El Tráfico Es Impredecible

Patrones de tráfico real varían:

Lunes 9am:    Pico por horas laborales
Viernes 5pm:  Caída cuando salen del trabajo
Black Friday: 10x tráfico normal
Momento viral: 100x tráfico normal (si tienes suerte)

Load testing te prepara para picos.

Tipos de Performance Testing

Load Testing (Carga)

Testea niveles de tráfico esperados:

// k6 load test - tráfico esperado
export const options = {
  stages: [
    { duration: '5m', target: 100 },  // Rampa subida
    { duration: '10m', target: 100 }, // Estado estable
    { duration: '5m', target: 0 },    // Rampa bajada
  ],
};

Objetivo: Verificar operación normal.

Stress Testing (Estrés)

Presiona más allá de límites esperados:

// k6 stress test - encontrar punto de quiebre
export const options = {
  stages: [
    { duration: '2m', target: 100 },
    { duration: '5m', target: 200 },
    { duration: '5m', target: 400 },
    { duration: '5m', target: 800 },  // Más allá de lo normal
    { duration: '2m', target: 0 },
  ],
};

Objetivo: Encontrar capacidad máxima y puntos de quiebre.

Spike Testing (Pico)

Testea aumentos súbitos de tráfico:

// k6 spike test - aumento súbito
export const options = {
  stages: [
    { duration: '1m', target: 50 },
    { duration: '30s', target: 500 }, // Pico súbito
    { duration: '2m', target: 500 },
    { duration: '30s', target: 50 },  // Regreso
  ],
};

Objetivo: Verificar que sistema maneja cambios súbitos.

Soak Testing (Remojo)

Testea rendimiento durante períodos extendidos:

// k6 soak test - duración extendida
export const options = {
  stages: [
    { duration: '5m', target: 100 },
    { duration: '8h', target: 100 },  // 8 horas
    { duration: '5m', target: 0 },
  ],
};

Objetivo: Encontrar memory leaks y degradación con el tiempo.

Métricas Clave a Rastrear

Tiempo de Respuesta

Cuánto tardan los requests en completarse:

p50 (mediana):  200ms - Mitad de requests más rápidos
p95:            500ms - 95% de requests más rápidos
p99:           1200ms - 99% de requests más rápidos
Max:           5000ms - Request más lento

Enfócate en p95/p99 — muestran peor experiencia de usuario.

Throughput

Requests procesados por unidad de tiempo:

Requests/segundo: 150 req/s
Transacciones/segundo: 30 tx/s
Transferencia datos: 15 MB/s

Mayor throughput significa más capacidad.

Tasa de Error

Porcentaje de requests fallidos:

Requests exitosos: 9,850
Requests fallidos:   150
Tasa error:        1.5% ← Muy alto para production

Meta: Bajo 1% tasa error, idealmente bajo 0.1%.

Uso de Recursos

Métricas del lado servidor:

CPU:      75% promedio, 95% pico
Memoria:  4GB / 8GB (50%)
Disk I/O: 200 IOPS
Red:      500 Mbps

Vigila cuellos de botella acercándose a límites.

Tu Primer Load Test

k6 (JavaScript)

// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 50,           // 50 usuarios virtuales
  duration: '5m',    // Correr 5 minutos
  thresholds: {
    http_req_duration: ['p(95)<500'], // 95% bajo 500ms
    http_req_failed: ['rate<0.01'],   // Menos de 1% errores
  },
};

export default function () {
  // Test homepage
  const homeResponse = http.get('https://example.com/');
  check(homeResponse, {
    'homepage status is 200': (r) => r.status === 200,
    'homepage loads fast': (r) => r.timings.duration < 500,
  });

  // Simular tiempo de pensamiento
  sleep(1);

  // Test API endpoint
  const apiResponse = http.get('https://example.com/api/products');
  check(apiResponse, {
    'api status is 200': (r) => r.status === 200,
    'api returns data': (r) => JSON.parse(r.body).length > 0,
  });

  sleep(2);
}

Ejecutar con: k6 run load-test.js

JMeter

JMeter usa configuración XML, típicamente creada via GUI:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan>
  <hashTree>
    <ThreadGroup>
      <stringProp name="ThreadGroup.num_threads">50</stringProp>
      <stringProp name="ThreadGroup.ramp_time">30</stringProp>
      <stringProp name="ThreadGroup.duration">300</stringProp>
      <HTTPSamplerProxy>
        <stringProp name="HTTPSampler.domain">example.com</stringProp>
        <stringProp name="HTTPSampler.path">/api/products</stringProp>
        <stringProp name="HTTPSampler.method">GET</stringProp>
      </HTTPSamplerProxy>
    </ThreadGroup>
  </hashTree>
</jmeterTestPlan>

Ejecutar con: jmeter -n -t test.jmx -l results.jtl

Locust (Python)

# locustfile.py
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)  # Tiempo de pensamiento

    @task(3)  # Mayor peso
    def view_homepage(self):
        self.client.get("/")

    @task(2)
    def view_products(self):
        self.client.get("/api/products")

    @task(1)
    def view_product_detail(self):
        self.client.get("/api/products/1")

Ejecutar con: locust -f locustfile.py --host=https://example.com

Mejores Prácticas

1. Testea en Ambientes Production-Like

El ambiente importa:

❌ Testing en localhost con base de 1GB
✓ Testing en staging con datos tamaño production

Resultados de localhost no predicen rendimiento en production

Iguala:

  • Especificaciones de servidores
  • Tamaño de base de datos
  • Configuración de red
  • Integraciones third-party

2. Usa Datos de Test Realistas

// Malo: Siempre mismo request
http.get('/api/users/1');

// Bueno: Requests variados, realistas
const userId = Math.floor(Math.random() * 10000) + 1;
http.get(`/api/users/${userId}`);

Varía parámetros para tocar diferentes code paths y comportamiento de caché.

3. Simula Comportamiento Real de Usuario

Usuarios no hacen click tan rápido como scripts:

export default function () {
  http.get('/');
  sleep(2);  // Tiempo pensamiento: leyendo homepage

  http.get('/products');
  sleep(3);  // Tiempo pensamiento: viendo productos

  http.post('/cart', { productId: 123 });
  sleep(1);  // Acción rápida
}

Incluye delays realistas entre acciones.

4. Define Criterios Pass/Fail Claros

Establece umbrales antes de testear:

export const options = {
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1000'],
    http_req_failed: ['rate<0.01'],
    http_reqs: ['rate>100'],  // Throughput mínimo
  },
};

Tests deben pasar o fallar automáticamente.

5. Testea Regularmente

Load testing no debe ser evento único:

# GitHub Actions - load test semanal
on:
  schedule:
    - cron: '0 2 * * 0'  # Cada domingo a las 2am

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: k6 run tests/load-test.js

Detecta regresiones antes de que lleguen a production.

Comparación de Herramientas

HerramientaLenguajeMejor ParaCurva Aprendizaje
k6JavaScriptDevelopers, CI/CDBaja
JMeterJava/XMLEquipos QA, GUIMedia
GatlingScalaAlto rendimientoMedia
LocustPythonEquipos PythonBaja
ArtilleryJavaScriptApps serverlessBaja

Eligiendo Herramienta

Elige k6 si:

  • Developers escriben tests
  • Necesitas integración CI/CD
  • Prefieres código sobre GUI

Elige JMeter si:

  • Equipo QA escribe tests
  • Necesitas diseño visual de tests
  • Necesitas ecosistema extenso de plugins

Elige Gatling si:

  • Necesitas alto rendimiento
  • Ambiente Scala/JVM
  • Reportes HTML detallados

Interpretando Resultados

Resultados Saludables

✓ http_req_duration..........: avg=180ms p95=320ms p99=450ms
✓ http_req_failed............: 0.02%
✓ http_reqs..................: 15000 (250/s)
✓ vus........................: 50

Tiempos de respuesta bajos, mínimos errores, throughput consistente.

Indicadores de Problemas

✗ http_req_duration..........: avg=2500ms p95=8000ms p99=15000ms
✗ http_req_failed............: 15%
  http_reqs..................: 3000 (50/s)
  vus........................: 50

Banderas rojas:

  • Altos tiempos de respuesta (especialmente p95/p99)
  • Tasa error arriba de 1%
  • Throughput cae bajo carga
  • Alto uso de recursos

Encontrando Cuellos de Botella

Cuando tests fallan, investiga:

  1. Código aplicación — Queries lentos, algoritmos ineficientes
  2. Base de datos — Optimización queries, índices, connection pooling
  3. Infraestructura — Límites CPU/memoria, ancho de banda red
  4. Third parties — APIs externos lentos, rate limits
// Agrega logging detallado para identificar cuellos de botella
const response = http.get('/api/users');
console.log(`DNS: ${response.timings.blocked}ms`);
console.log(`Connect: ${response.timings.connecting}ms`);
console.log(`TLS: ${response.timings.tls_handshaking}ms`);
console.log(`Waiting: ${response.timings.waiting}ms`);
console.log(`Receiving: ${response.timings.receiving}ms`);

FAQ

¿Qué es load testing?

Load testing mide cómo un sistema se desempeña bajo tráfico esperado de usuarios. Simula muchos usuarios concurrentes haciendo requests simultáneamente para verificar que la aplicación maneja cargas normales y pico sin degradación de rendimiento. A diferencia de testing funcional que verifica si features funcionan, load testing verifica si features funcionan bajo condiciones de tráfico realistas. El objetivo es responder: “¿Puede nuestro sistema manejar el número esperado de usuarios?”

¿Cuál es la diferencia entre load testing y stress testing?

Load testing simula niveles de tráfico esperados para verificar operación normal. Stress testing intencionalmente excede límites esperados para encontrar puntos de quiebre. Piensa en load testing como “¿podemos manejar tráfico normal?” y stress testing como “¿cuándo nos quebramos?” Load testing usa números realistas de usuarios; stress testing presiona hasta que el sistema falla. Ambos son valiosos — load testing para validación, stress testing para planificación de capacidad.

¿Qué métricas debo rastrear en load testing?

Rastrea estas métricas clave: Percentiles de tiempo de respuesta (p50, p95, p99) muestran cómo usuarios experimentan el rendimiento — p95 significa 95% de requests son más rápidos que este valor. Throughput (requests por segundo) muestra capacidad. Tasa de error (porcentaje de requests fallidos) debe mantenerse bajo 1%. Uso de recursos (CPU, memoria, disk I/O) revela cuellos de botella. Enfócate en p95 tiempo de respuesta como métrica principal — representa experiencia real del usuario mejor que promedios.

¿Qué herramientas se usan para load testing?

Herramientas populares de load testing incluyen k6 (basado en JavaScript, moderno, amigable para developers), JMeter (Java, basado en GUI, plugins extensivos), Gatling (Scala, alto rendimiento), y Locust (basado en Python, fácil de aprender). k6 es ideal para developers que quieren tests como código en CI/CD. JMeter sirve a equipos QA que prefieren diseño visual de tests. Elige basándote en skills del equipo y necesidades de integración.

Ver También