DEV Community

Cover image for Vegeta Teste de Carga: Tutorial de HTTP com Taxa Constante
Lucas
Lucas

Posted on • Originally published at apidog.com

Vegeta Teste de Carga: Tutorial de HTTP com Taxa Constante

Você quer medir como sua API se comporta exatamente a 500 requisições por segundo, não “o mais rápido que N threads conseguirem enviar”. A maioria das ferramentas de carga fixa a concorrência e deixa a taxa variar. O Vegeta faz o inverso: você define a taxa, e ele tenta enviar esse volume de requisições por segundo independentemente da velocidade de resposta do servidor. Isso importa quando você precisa validar throughput, latência e SLOs sob uma carga-alvo.

Experimente o Apidog hoje

O que é Vegeta

Vegeta é uma ferramenta de teste de carga HTTP via linha de comando, escrita em Go. Também pode ser usada como biblioteca Go, mas este guia foca na CLI.

A ideia principal é simples:

você define uma taxa constante de requisições, e o Vegeta tenta manter esse ritmo durante todo o teste.

Exemplo: “envie 100 requisições por segundo por 30 segundos”. Se o servidor ficar lento, o Vegeta continua emitindo novas requisições conforme o cronograma, em vez de esperar as anteriores terminarem.

Isso cria um modelo de carga aberto, mais próximo de tráfego real: usuários chegam em seu próprio ritmo; eles não esperam seu endpoint lento terminar para que o próximo usuário apareça.

Carga baseada em taxa vs. baseada em concorrência

A diferença prática é esta:

  • ferramentas baseadas em concorrência fixam usuários virtuais, threads ou workers;
  • ferramentas baseadas em taxa fixam a quantidade de requisições por segundo.

Em um modelo baseado em concorrência, cada worker geralmente executa um loop:

enviar requisição -> aguardar resposta -> enviar próxima requisição
Enter fullscreen mode Exit fullscreen mode

Se o servidor fica lento, o loop demora mais. Como consequência, a taxa real de requisições cai. A ferramenta “recua” sem você perceber.

Em um modelo baseado em taxa, como no Vegeta, você fixa a taxa de chegada. Se o servidor não acompanha, as requisições começam a se acumular, a latência sobe e os erros aparecem no relatório.

Use cada modelo para perguntas diferentes:

Pergunta Modelo mais adequado
Quantos usuários simultâneos minha API suporta? Concorrência
O que acontece com 2.000 requisições por segundo? Taxa
Em qual RPS a latência começa a degradar? Taxa
Como duas builds se comportam sob a mesma carga? Taxa

Para uma visão mais ampla do ecossistema, veja as principais ferramentas de teste de carga de API.

Instalar Vegeta

Escolha a opção adequada para seu ambiente.

macOS com Homebrew

brew update && brew install vegeta
Enter fullscreen mode Exit fullscreen mode

Outros gerenciadores de pacotes

# MacPorts
port install vegeta

# Arch Linux
pacman -S vegeta

# FreeBSD
pkg install vegeta
Enter fullscreen mode Exit fullscreen mode

Compilar a partir do código-fonte

Com Go instalado:

git clone https://github.com/tsenart/vegeta
cd vegeta
make vegeta
Enter fullscreen mode Exit fullscreen mode

Você também pode baixar um binário pré-compilado pela página de releases do GitHub.

Confirme a instalação:

vegeta --help
Enter fullscreen mode Exit fullscreen mode

O pipeline principal

O Vegeta foi desenhado para funcionar bem com pipes Unix:

echo "GET http://localhost:8080/" | vegeta attack -duration=5s -rate=100 | vegeta report
Enter fullscreen mode Exit fullscreen mode

Leia o comando da esquerda para a direita:

  1. echo escreve um alvo HTTP: método e URL.
  2. vegeta attack lê o alvo pela entrada padrão e dispara 100 requisições por segundo por 5s.
  3. vegeta report lê os resultados e imprime um resumo.

Esse teste gera aproximadamente:

100 req/s * 5s = 500 requisições
Enter fullscreen mode Exit fullscreen mode

A flag -rate aceita requisições por unidade de tempo:

-rate=100       # 100 requisições por segundo
-rate=100/1s    # equivalente
-rate=50/500ms  # 50 requisições a cada 500 ms
Enter fullscreen mode Exit fullscreen mode

Use -rate=0 apenas quando quiser remover o limite e enviar o máximo possível. Isso muda o tipo de teste: deixa de ser uma carga constante controlada e vira um teste de throughput máximo.

Como ler o relatório

Um relatório de texto se parece com isto:

Requests      [total, rate, throughput]  500, 100.20, 100.18
Duration      [total, attack, wait]      4.991s, 4.990s, 1.2ms
Latencies     [min, mean, 50, 90, 95, 99, max]  412us, 1.3ms, 1.1ms, 1.9ms, 2.4ms, 5.1ms, 12ms
Bytes In      [total, mean]              128500, 257.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:500
Error Set:
Enter fullscreen mode Exit fullscreen mode

Na prática, avalie nesta ordem:

  1. Latencies
    • 50: mediana.
    • 95: 95º percentil.
    • 99: cauda lenta. Se esse valor está alto, usuários reais sentirão o problema.
  2. Success [ratio]
    • Deve estar próximo de 100% para uma carga suportada.
  3. Status Codes
    • Verifique se há 5xx, 429 ou outros códigos inesperados.
  4. Error Set
    • Deve estar vazio em uma execução saudável.

Uma média boa não compensa um percentil 99 ruim. Em APIs, a cauda costuma ser onde os incidentes começam.

Salve os resultados antes de gerar relatórios

Para testes rápidos, enviar direto para vegeta report é suficiente. Para qualquer execução que você queira comparar, versionar ou anexar ao CI, salve o arquivo binário de resultados.

echo "GET http://localhost:8080/" | \
  vegeta attack -duration=10s -rate=200 -output=results.bin
Enter fullscreen mode Exit fullscreen mode

Depois gere relatórios a partir do arquivo.

Relatório de texto

vegeta report results.bin
Enter fullscreen mode Exit fullscreen mode

JSON para dashboard ou automação

vegeta report -type=json results.bin > metrics.json
Enter fullscreen mode Exit fullscreen mode

Histograma de latência

vegeta report -type='hist[0,2ms,5ms,10ms,25ms,100ms]' results.bin
Enter fullscreen mode Exit fullscreen mode

O histograma mostra quantas requisições caíram em cada faixa de latência. É útil para identificar se a maioria das respostas está concentrada em uma faixa pequena ou se há dispersão significativa.

Criar um arquivo de alvos

APIs reais raramente são testadas com um único GET. Coloque seus endpoints em um arquivo e passe-o com -targets.

Crie targets.txt:

GET http://localhost:8080/api/users

POST http://localhost:8080/api/users
Content-Type: application/json
@./payload.json

GET http://localhost:8080/api/users/42
Enter fullscreen mode Exit fullscreen mode

Crie o corpo da requisição em payload.json:

{ "name": "Ada", "role": "engineer" }
Enter fullscreen mode Exit fullscreen mode

Execute:

vegeta attack -targets=targets.txt -rate=50 -duration=30s | vegeta report
Enter fullscreen mode Exit fullscreen mode

Regras do formato:

  • a primeira linha de cada alvo é MÉTODO URL;
  • cabeçalhos vêm logo abaixo, no formato Chave: Valor;
  • uma linha iniciada com @ referencia um arquivo usado como corpo da requisição;
  • uma linha em branco separa um alvo do próximo;
  • linhas iniciadas com # são comentários.

O Vegeta percorre os alvos em ordem e repete a lista até a duração terminar.

Adicionar autenticação

Para adicionar cabeçalhos globais, use -header.

Exemplo com Bearer Token:

vegeta attack -targets=targets.txt -rate=50 -duration=30s \
  -header="Authorization: Bearer $TOKEN" | vegeta report
Enter fullscreen mode Exit fullscreen mode

Você também pode adicionar outros cabeçalhos:

vegeta attack -targets=targets.txt -rate=50 -duration=30s \
  -header="Authorization: Bearer $TOKEN" \
  -header="X-Request-Source: load-test" | vegeta report
Enter fullscreen mode Exit fullscreen mode

Usar formato JSON para alvos

Para geração programática, o Vegeta também aceita alvos em JSON. Cada linha é um objeto JSON.

Exemplo:

{"method": "GET", "url": "http://localhost:8080/api/users"}
{"method": "POST", "url": "http://localhost:8080/api/users", "header": {"Content-Type": ["application/json"]}, "body": "eyJuYW1lIjoiQWRhIn0="}
Enter fullscreen mode Exit fullscreen mode

Execute com -format=json:

vegeta attack -format=json -targets=targets.json -rate=100 -duration=30s | vegeta report
Enter fullscreen mode Exit fullscreen mode

O campo body deve estar em base64.

Esse formato funciona bem quando você gera alvos em tempo real. Para reduzir uso de memória em streams grandes, use -lazy.

generate-targets | vegeta attack -format=json -lazy -rate=100 -duration=30s | vegeta report
Enter fullscreen mode Exit fullscreen mode

Gerar gráficos e comparar execuções

Um único número pode esconder degradações no meio do teste. Para visualizar latência ao longo do tempo, use vegeta plot.

vegeta attack -targets=targets.txt -rate=100 -duration=60s | \
  vegeta plot > plot.html
Enter fullscreen mode Exit fullscreen mode

Abra plot.html no navegador. Você verá uma série temporal da latência durante a execução.

Para comparar diferentes níveis de carga:

vegeta attack -rate=50  -duration=30s -targets=targets.txt -output=50qps.bin
vegeta attack -rate=100 -duration=30s -targets=targets.txt -output=100qps.bin

vegeta plot 50qps.bin 100qps.bin > compare.html
Enter fullscreen mode Exit fullscreen mode

Em ambientes sem interface gráfica, exporte CSV:

vegeta encode -to=csv results.bin > results.csv
Enter fullscreen mode Exit fullscreen mode

Encontrar o limite de capacidade

Um fluxo simples para encontrar o ponto de degradação:

for rate in 50 100 200 400 800; do
  echo "Executando teste com ${rate} req/s"

  vegeta attack \
    -targets=targets.txt \
    -rate=${rate} \
    -duration=30s \
    -output="results-${rate}.bin"

  vegeta report "results-${rate}.bin" > "report-${rate}.txt"
done
Enter fullscreen mode Exit fullscreen mode

Depois compare:

grep -E "Requests|Latencies|Success|Status Codes" report-*.txt
Enter fullscreen mode Exit fullscreen mode

Procure o primeiro ponto em que:

  • o percentil 95 ou 99 sobe de forma relevante;
  • a taxa de sucesso cai;
  • aparecem códigos 5xx, 429 ou timeouts;
  • o throughput fica abaixo da taxa solicitada.

Esse ponto indica que a API começou a não acompanhar a carga desejada.

Quando usar o Vegeta

Use Vegeta quando a pergunta for sobre taxa, latência e capacidade:

  • medir throughput e latência em um RPS específico;
  • descobrir em qual taxa a latência começa a subir;
  • comparar duas builds sob carga idêntica;
  • comparar duas configurações de infraestrutura;
  • automatizar testes de carga em shell ou CI;
  • gerar relatórios simples sem depender de GUI.

Ele é uma ferramenta focada. Envia requisições HTTP em uma taxa definida e mede como o servidor responde.

Ele não é ideal para:

  • jornadas complexas com múltiplos passos e ramificações;
  • simular navegação realista de usuários;
  • validar regras de negócio;
  • verificar schemas ou campos específicos no corpo da resposta.

Esse foco é positivo: mantém os testes repetíveis, scriptáveis e fáceis de interpretar.

Se estiver comparando alternativas, veja também os guias sobre teste de carga k6 e teste de carga JMeter. Para conceitos e métricas, comece pelo tutorial de teste de desempenho de API.

Onde o teste funcional entra

Teste de carga responde:

“A API é rápida o suficiente sob esta carga?”

Ele não responde:

“A API está retornando os dados corretos?”

Uma execução do Vegeta pode mostrar 100% de respostas 200 enquanto o endpoint retorna o usuário errado, um preço desatualizado ou um JSON inválido. Para uma ferramenta de carga, isso ainda pode parecer sucesso.

Correção exige outro tipo de validação:

  • status esperado;
  • cabeçalhos esperados;
  • campos JSON;
  • schema;
  • regras de negócio;
  • encadeamento entre requisições.

Isso é teste funcional, e deve acontecer antes ou junto dos testes de carga.

É aqui que o Apidog complementa o Vegeta. No Apidog, você cria cenários funcionais com asserções sobre status, cabeçalhos e campos JSON, encadeia requisições e usa dados externos. Depois, o Vegeta mede se os caminhos já validados continuam rápidos sob centenas ou milhares de requisições por segundo.

Executar testes funcionais no CI com Apidog CLI

O Apidog oferece uma CLI headless para executar cenários funcionais em pipelines.

Instale com Node:

npm install -g apidog-cli
Enter fullscreen mode Exit fullscreen mode

Execute um cenário, pasta ou suíte salvo por ID:

apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
  -t <scenarioOrSuiteId> \
  -e <environmentId> \
  -r cli,html,junit
Enter fullscreen mode Exit fullscreen mode

Parâmetros principais:

  • -t: ID do cenário, pasta ou suíte;
  • -e: ID do ambiente;
  • -r: formatos de relatório, como cli, html, json e junit.

A saída junit funciona bem em dashboards de CI.

Veja o tutorial da linha de comando da CLI do Apidog e o guia de pipeline CI/CD para um fluxo passo a passo.

Um pipeline saudável fica assim:

1. Executar testes funcionais
2. Bloquear o pipeline se asserções falharem
3. Executar Vegeta nos endpoints aprovados
4. Publicar relatórios de carga
Enter fullscreen mode Exit fullscreen mode

Perguntas frequentes

Vegeta suporta requisições POST com corpo?

Sim. No arquivo de alvos HTTP, defina o método e a URL na primeira linha, adicione Content-Type e referencie o corpo com @./payload.json.

Exemplo:

POST http://localhost:8080/api/users
Content-Type: application/json
@./payload.json
Enter fullscreen mode Exit fullscreen mode

No formato JSON, use method, url e body em base64.

O que -rate=0 faz?

Remove o limite de taxa e envia requisições tão rápido quanto workers e conexões permitirem.

Isso é útil para medir throughput máximo, mas não para um teste controlado de taxa constante. Para medições repetíveis, defina uma taxa explícita, como -rate=100.

Como leio os percentis de latência?

A linha Latencies mostra mínimo, média, mediana, percentis 90, 95, 99 e máximo.

Priorize:

  • 95: comportamento lento para uma parte relevante dos usuários;
  • 99: cauda extrema;
  • max: pior caso observado.

A média pode esconder problemas, então não use apenas mean.

Vegeta valida se minha API retorna dados corretos?

Não. Vegeta mede throughput, latência, códigos de status e erros de transporte. Ele não valida corpo da resposta, schema ou regras de negócio.

Combine Vegeta com uma ferramenta de teste funcional para validar correção antes de medir performance.

Como executo Vegeta em CI?

Como ele é um binário de linha de comando, basta adicionar uma etapa shell.

Exemplo:

vegeta attack \
  -targets=targets.txt \
  -rate=100 \
  -duration=30s \
  -output=results.bin

vegeta report results.bin
vegeta report -type=json results.bin > metrics.json
Enter fullscreen mode Exit fullscreen mode

Publique results.bin, metrics.json e o relatório textual como artefatos do build.

Para evitar medir endpoints quebrados, rode primeiro um gate funcional, como a CLI do Apidog, e só depois execute a etapa de carga.

Top comments (0)