Módulo 7 · Pruebas

Lección 36 — Pruebas de carga (k6)

Encontrar el cuello de botella antes que la cola del concierto.

Publicada
En esta lección
  1. Ejercicio 1 — El script
  2. Ejercicio 2 — El checkout bajo presión
  3. Ejercicio 3 — El cuello, localizado
  4. Ejercicio 4 — La curva completa
  5. Ejercicio 5 — La mejora medida
  6. Entrega

El pico de pre-venta bajo control. Sin solutions.md hasta entregar.

Ejercicio 1 — El script

  1. Instala k6 y escribe load/browse.js: 50 VUs, rampa 1m/3m/1m, GET /events y /events/:id con think time 0.5-2 s. Thresholds: p95<300 ms, rate error<0.1%.
  2. Corre contra manage.py runserver y luego contra gunicorn (4 workers): pega los dos p95. La diferencia ES la lección (¿qué estabas midiendo la primera vez?).
  3. Añade el check de corrección: el detalle devuelve seats_available >= 0 y el schema del listado cumple el contrato (35). La carga sin corrección solo mide velocidad del caos.

Ejercicio 2 — El checkout bajo presión

  1. Escribe load/checkout.js (el de la lección): mezcla 70/20/9/1, thresholds de p95/p99, y la autenticación por usuario de test (18). Corre la meseta de 200 × 5 min contra el entorno honesto (gunicorn+PG real+seed de 2M asientos).
  2. El 409 como éxito: añade rate_409 como métrica propia (Counter) y verifica que en la meseta los 409 NO cuentan como fallos pero SÍ se registran (¿cuántos? ¿qué porcentaje del total de intentos?).
  3. El seed realista: 50k eventos, 2M asientos con distribuciones (eventos pequeños 500 asientos vs arenas 20k). Corre el checkout SOLO contra arenas y SOLO contra eventos pequeños: ¿difiere el p95? ¿Por qué (¿el lock del evento grande, 10?)?

Ejercicio 3 — El cuello, localizado

  1. Con pg_stat_statements: en la meseta de 200, lista las 5 queries top por tiempo total. ¿Cuál es y cuánto del p95 explica?
  2. El pool de conexiones (39): mide con SELECT * FROM pg_stat_activity durante la corrida: ¿cuántas conexiones en idle in transaction? ¿El p95 del endpoint lento coincide con "esperando conexión"? Documenta el finding.
  3. La latencia remota: la pasarela fake con delay configurable (0/200/500 ms). Corre 3 mesetas: ¿cuánto del p99 del checkout es la pasarela? ¿Qué conclusiones de capacidad PUEDES sacar sin controlar la red real? (la 54 tratará el timeout/breaker).

Ejercicio 4 — La curva completa

  1. Ejecuta el escenario completo (rampa/meseta/pico 400/descarga) y grafica (o lee del JSON): ¿el pico degrada elegante (409/429 crecen, latencia estable) o colapsa (timeouts en cadena)? Pega las cifras.
  2. La descarga: después del pico, ¿en cuántos segundos vuelve el p95 a la línea base? Si tarda >60 s: ¿qué acumuló (cola de Celery pendiente, caché invalidada, conexiones zombis)? Documenta el finding.
  3. El número de capacidad: con la meseta limpia, escribe load/results/2027-09-28.md con hardware, seed, escenario, resultados y conclusiones en ≤15 líneas. Es el documento que el negocio entiende.

Ejercicio 5 — La mejora medida

  1. Toma el cuello del ejercicio 3 (el UPDATE masivo de asientos) y aplica la mejora: un solo UPDATE con CASE/bulk_update por lotes (09). Re-corre la MISMA meseta: pega el antes/después del p95 y de pg_stat_statements.
  2. ¿Subió la capacidad? ¿A cuántos VUs aguanta ahora la meseta limpia? ¿Qué mejora aplicaría SIGUIENTE y por qué (¿partición por evento, 55, o replicas de lectura)?
  3. El plan de preventa: con el número de capacidad medido, escribe la decisión de producto: ¿admito N usuarios por turno al checkout (23/32) o escalo horizontal (55)? Justifica con los números de la corrida.

Entrega

Pega los p95 de runserver vs gunicorn, el resultado de la meseta con 409s, el finding del cuello con pg_stat_statements y el before/after de la mejora. Después: Lección 37 — Perfilado (módulo 8).