Voltar para Artigos
DevOps★ Destaque5 min de leitura

Quebrando sua API de propósito: Testes de Carga com K6

Como identificar gargalos de infraestrutura antes da Black Friday. Cenários de Stress e Spike testing, thresholds de latência (p95), variáveis de ambiente e a regra de ouro de nunca testar em produção.

12 de agosto de 2026

Você testa a API no Postman, ela responde em 25ms e você faz o deploy. No dia de um pico de acessos, 500 usuários batem na mesma rota no mesmo segundo. O Node.js não dá conta de tantas conexões de banco de dados simultâneas, o event loop enfileira e a latência vai para 8000ms (8 segundos). Os usuários dão refresh, piorando o gargalo, até o processo cair por falta de RAM (OOM). Para prever isso, usamos Testes de Carga.

Grafana K6: O Motor em Go

O K6 usa um runtime Go com V8 para JavaScript — isso significa que ele pode simular 10.000 usuários virtuais em uma única máquina sem o overhead de threads. Cada VU (Virtual User) executa o script em loop independentemente, simulando sessões reais de usuários com pensão entre as requisições (sleep). Os testes são definidos em três fases: ramp-up (escala gradual), sustain (carga constante) e ramp-down (diminui para ver se o sistema se recupera).

appointments.js
import http from 'k6/http';
import { check, sleep } from 'k6';

// 1. Definição do cenário e métricas de aceite
export const options = {
  stages: [
    // Spike testing: sobe para 200 usuários em apenas 10 segundos
    { duration: '10s', target: 200 }, 
    // Mantém o estresse por 1 minuto
    { duration: '1m', target: 200 },
    // Volta a zero para ver se o sistema se recupera (cool down)
    { duration: '20s', target: 0 },
  ],
  thresholds: {
    // P95: 95% das requisições PRECISAM ser respondidas em menos de 250ms
    http_req_duration: ['p(95) < 250'], 
    // Taxa de falha (erros 500 ou timeout) deve ser estritamente menor que 1%
    http_req_failed: ['rate < 0.01'],
  },
};

// 2. A jornada do Usuário Virtual (VU)
export default function () {
  // Lemos a URL através de variável de ambiente para flexibilidade
  const BASE_URL = __ENV.API_URL || 'http://localhost:3333';

  const res = http.get(`${BASE_URL}/appointments`);
  
  // Valida o status code para não mascarar falhas
  check(res, { 
    'status is 200': (r) => r.status === 200,
    'is not error payload': (r) => !r.body.includes('error')
  });
  
  // Espera entre 0.5s e 1.5s antes de bater de novo (simulando tempo de leitura)
  sleep(Math.random() + 0.5);
}

Interpretando os Resultados

Os thresholds são a parte mais importante do script: se p(95) < 250 falhar, o K6 encerra com exit code 1 e o CI/CD marca o pipeline como falho. Isso impede que um deploy continue se uma nova feature degradou a performance acima do SLA. O threshold de http_req_failed < 0.01 captura erros HTTP (5xx, timeouts) — se mais de 1% das requisições falham sob carga, a API não é confiável para o cenário testado.

NUNCA FAÇA TESTE DE CARGA EM PRODUÇÃO. Além de inflar o banco de dados com lixo gerado pelo teste, você estará promovendo um Ataque DDoS contra o seu próprio sistema real. Provisione um ambiente de Staging espelhado (mesmo banco de dados, mesma memória) para validar limites antes de grandes eventos.

Conclusão

O K6 integra nativamente com o Grafana Cloud (mesmo fabricante), permitindo visualizar em tempo real as métricas enquanto o teste roda: latência por endpoint, taxa de erros, VUs ativos. Para colocar no CI/CD, use k6 run --exit-on-running com --out json=resultado.json para arquivar os resultados. Uma regressão de performance (p95 passou de 50ms para 300ms após um PR) é tão crítica quanto uma regressão funcional — e o K6 no pipeline garante que seja detectada antes do merge.

Testes de Carga não verificam a regra de negócio; eles verificam se a infraestrutura sobrevive ao tráfego. Escrever scripts K6 e acoplá-los no CI/CD garante que sua nova feature não introduziu um gargalo catastrófico (como um N+1 invisível no TypeORM) que só seria descoberto tarde demais.