Saltar al contenido principal
20 ago 2026k6 parametrizacion csv json

Por Lucas Yoris · Performate

Parametrización bien hecha: CSV, JSON y datos compartidos en k6

Parametrización k6 con CSV/JSON: SharedArray, datasets memory-safe y tráfico sesgado—docs oficiales de datos k6 y datos de prueba conscientes de GDPR.

Tu script de checkout usa userId: 42 en cada iteración. El pool de conexiones a la base de datos se calienta sobre una sola fila, el caché de sesión nunca se invalida de verdad y el p99 que ves en staging no se parece en nada al perfil de producción donde el 3 % de los usuarios concentra el 40 % del tráfico.

La parametrización en k6 no es un detalle de comodidad: define qué caminos del sistema ejercitas bajo carga. Un dataset mal elegido puede hacer pasar una prueba que oculta cuellos de botella reales, o inflar latencia porque repites el mismo tenant bloqueado. En esta guía verás por qué importa el sesgo de datos, cómo cargar CSV y JSON con SharedArray sin reventar la memoria del generador, y qué señales deberían frenar un dataset antes de escalar VUs.

Por qué la parametrización cambia el rendimiento—no solo la cobertura funcional

A nivel funcional, un request con sku: 'SKU-100' y otro con sku: 'SKU-900' pueden devolver 200. Bajo concurrencia, ejercitan recursos distintos:

  • Particionamiento de datos — tenants, regiones o shards distintos enrutan a nodos, réplicas o índices diferentes.
  • Cachés calientes vs fríos — repetir el mismo ID mantiene líneas de caché artificiales; IDs dispersos simulan misses reales.
  • Contención de locks — updates sobre la misma fila serializan transacciones que en prod se reparten.
  • Rate limits por clave — API keys, IPs o user IDs compartidos en el dataset agotan cuotas antes de lo esperado.

Piensa en un supermercado donde todos los clientes de prueba van al mismo pasillo. La cola del pasillo no predice el sábado real.

Cuando los literales hardcodeados engañan

Las suites funcionales prueban casos representativos. No prueban que 10 000 SKUs distintos con distribución zipfiana mantengan el catálogo bajo 400 ms en p95. Eso exige datasets parametrizados, estrategias de selección alineadas a analytics y, cuando corresponda, datos compatibles con GDPR—no un array de tres IDs copiados del ticket de Jira.

Combina parametrización con ejecutores arrival-rate al modelar cargas abiertas (VU vs arrival) para que la forma de tráfico y la diversidad de datos coincidan con la pregunta que estás haciendo.

Implementación práctica con k6: SharedArray, CSV y selección sesgada

Carga datasets una sola vez por instancia de k6 con SharedArray—comparte memoria entre VUs en lugar de duplicar el archivo por goroutine. Elige la estrategia de pick según el sesgo de producción, no uniforme por defecto.

Script de ejemplo (ilustrativo—no es una prueba lista para producción). El snippet usa paths, tokens y datasets ficticios. Adapta archivos, auth y umbrales a tu entorno.

Qué demuestra este ejemplo:

  • Carga memory-safe: SharedArray parsea orders.csv una vez; cada VU lee filas sin copiar el dataset entero en memoria por iteración.
  • Selección sesgada: pickWeightedRow() favorece tier=enterprise (~15 %) como en analytics de prod, no picks uniformes.
  • Cardinalidad realista: 5 000 filas de pedidos simulan contención distribuida en lugar de un solo orderId.
  • Tags por segmento: tags: { tier: row.tier } permite umbrales y reportes por segmento de cliente en el summary de k6.
import http from 'k6/http';
import { check, sleep } from 'k6';
import { SharedArray } from 'k6/data';

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

// SharedArray: parseo único, lectura compartida entre VUs
const orders = new SharedArray('orders', () => {
  const raw = open('./data/orders.csv');
  return raw.split('\n').slice(1).map((line) => {
    const [orderId, sku, tier] = line.split(',');
    return { orderId, sku, tier: tier.trim() };
  });
});

// Sesgo enterprise ~15 % — ajusta pesos desde analytics
function pickWeightedRow() {
  const roll = Math.random();
  if (roll < 0.15) {
    const enterprise = orders.filter((r) => r.tier === 'enterprise');
    return enterprise[Math.floor(Math.random() * enterprise.length)];
  }
  return orders[Math.floor(Math.random() * orders.length)];
}

export const options = {
  scenarios: {
    checkout_param: {
      executor: 'constant-arrival-rate',
      rate: 50,
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 30,
      maxVUs: 120,
      exec: 'checkoutWithData',
    },
  },
  thresholds: {
    'http_req_duration{tier:enterprise}': ['p(95)<900', 'p(99)<1400'],
    'http_req_duration{tier:standard}': ['p(95)<500', 'p(99)<800'],
    http_req_failed: ['rate<0.01'],
  },
};

export function checkoutWithData() {
  const row = pickWeightedRow();
  const body = JSON.stringify({ orderId: row.orderId, sku: row.sku, qty: 1 });

  const res = http.post(`${BASE}/v1/checkout`, body, {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${__ENV.TOKEN}`,
    },
    tags: { tier: row.tier, route: 'checkout' },
  });

  check(res, { 'checkout 2xx': (r) => r.status >= 200 && r.status < 300 });
  sleep(0.2);
}

Patrones que funcionan

  • SharedArray para CSV/JSON — evita O(VUs × filas) en RAM; consulta la documentación de parametrización.
  • Pesos desde analytics — exporta distribuciones de tenant, SKU o región desde tu warehouse y codifica el sesgo en el picker.
  • Datasets sintéticos — genera IDs con Faker o scripts offline; elimina PII antes de commitear archivos (datos GDPR).
  • JSON para payloads anidados — cuando el CSV se vuelve frágil, usa SharedArray con JSON.parse(open('./data/users.json')).

Anti-patrones a evitar

  • Leer el CSV entero con open() dentro de default function—multiplica memoria por VU.
  • Pick uniforme cuando prod es zipfiana—subestimas hotspots en catálogo o billing.
  • Commitear datasets con emails, DNI o tokens reales de staging.

Tip pro (comando de ejemplo): valida cardinalidad antes de escalar VUs.

k6 run checkout-param.js --iterations 1 --vus 1 -e API_BASE=https://staging.example.com

Qué demuestra este comando: una corrida mínima confirma que el CSV se parsea, los picks resuelven y los tags aparecen en el summary antes de quemar staging con arrival rate alto.

Marco de decisión: CSV vs JSON vs sintético en runtime

SituaciónAcción recomendada
Miles de filas tabulares (SKUs, order IDs)CSV + SharedArray; pesos por columna de segmento
Payloads anidados o arrays variablesJSON + SharedArray; un objeto por fila lógica
PII prohibida en repoGeneración offline sintética; nunca datos de prod sin anonimizar
Sesgo zipfiano fuerte (top 1 % concentra tráfico)Picker ponderado o muestreo estratificado, no Math.random() plano
CI con artefacto grandeDataset reducido para smoke; dataset completo solo en nightly (CI/CD)

Usa CSV si el dataset es tabular, versionable en git y lo mantienen QA o datos con diff legible.

Usa JSON si cada fila incluye estructuras anidadas (headers, bodies, metadata de auth por usuario).

Usa generación sintética si la gobernanza prohíbe datasets reales—even anonimizados—en el repositorio de pruebas.

Observabilidad, documentación y siguientes pasos

Los datasets parametrizados solo sirven si el equipo sabe qué sesgo modelaron. Antes de escalar tráfico:

  • Documenta tamaño del dataset, fuente (export analytics, sintético) y distribución de pesos por segmento.
  • Verifica que no quede PII en archivos commiteados—revisa con grep o scanner en CI.
  • Configura umbrales por tag de segmento (tier, region) cuando los SLO difieren por cliente.
  • Archiva hash del dataset junto al git SHA de cada corrida de regresión.
  • Revalida pesos trimestralmente cuando producto cambia mix de tenants o catálogo.

Cómo Performate simplifica parametrización sin loaders ad hoc

Mantener scripts CSV repartidos en tres repos no escala. Abajo hay un ejemplo concreto de flujo para checkout parametrizado por tier—adapta nombres y archivos a tu analytics.

Ejemplo: dataset de pedidos con sesgo enterprise sin escribir SharedArray a mano

  1. Importa una colección Postman con el request de checkout y variables {{orderId}}, {{sku}}, {{tier}}. Problema resuelto: una sola fuente de verdad en lugar de scripts CSV duplicados por entorno.
  2. Vincula un archivo CSV o JSON en el panel de datos del escenario—Performate inyecta filas por iteración como lo haría SharedArray. Problema resuelto: bindings visuales sin pegamento de parseo en cada script nuevo.
  3. Define pesos de segmento en el editor (p. ej. 15 % enterprise, 85 % standard) alineados a la última semana en prod. Problema resuelto: sesgo honesto sin reescribir funciones pickWeighted en cada sprint.
  4. Aplica tags de escenario tier:enterprise y tier:standard desde columnas del dataset. Problema resuelto: reportes segmentados coinciden con el modelo de tags del ejemplo k6 de arriba.
  5. Corre contra staging y abre la vista de comparación—filtra por tier y verifica si enterprise arrastra la cola de p99. Problema resuelto: backend y producto debaten un export, no tres CSVs bifurcados.
  6. Exporta el script k6 generado para gates en CI (pruebas de carga en CI/CD) con el mismo dataset y pesos que la iteración local.

Ese flujo conecta directo con el cta de este post: escenarios ejecutables, umbrales y reportes compartibles sin perder días en código pegamento.

Cierre

El riesgo de datos en pruebas de carga es un problema de sesgo, no solo de volumen. Carga datasets con SharedArray, modela la distribución que analytics muestra en prod y etiqueta segmentos para que los umbrales reflejen SLO reales por cliente.

Corre contra staging con el dataset de esta semana antes de tu próxima revisión de capacidad—y anota qué segmento concentra la latencia que importa a tu SLO.

Try Performate free | Book a demo | k6 data parameterization

¿Listo para optimizar el rendimiento de tu API?

Usa Performate para convertir este playbook en escenarios k6 ejecutables, umbrales y reportes compartibles sin perder días en código pegamento.

← Volver a todas las entradas