DEV Community

Cover image for wrk: Como Fazer Teste de Carga em API pela Linha de Comando
Lucas
Lucas

Posted on • Originally published at apidog.com

wrk: Como Fazer Teste de Carga em API pela Linha de Comando

Você lançou um endpoint. Ele responde no navegador, mas isso não diz o que acontece quando 400 clientes acessam ao mesmo tempo. A latência continua estável? O p99 dispara? O servidor aguenta 1.000 requisições por segundo ou começa a falhar em 300?

Experimente o Apidog hoje

O wrk ajuda a responder essas perguntas. Ele é uma ferramenta de linha de comando para gerar carga HTTP contra uma URL e medir throughput, latência e comportamento sob concorrência.

O que é o wrk e quando usá-lo

wrk é uma ferramenta moderna de benchmark HTTP. Ela usa múltiplas threads e um loop de eventos escalável (epoll no Linux, kqueue no macOS), então uma única máquina multi-core consegue gerar bastante tráfego sem precisar de vários geradores de carga.

Use o wrk para responder perguntas como:

  • Quantas requisições por segundo este endpoint sustenta?
  • Como a latência se comporta na mediana, no p90 e no p99?
  • O serviço mantém estabilidade depois de 30 segundos, 2 minutos ou mais?
  • Qual mudança de código piorou ou melhorou o throughput?

Importante: wrk é uma ferramenta de benchmark, não uma ferramenta de teste funcional. Ele mede velocidade. Ele não valida se o JSON está correto, se o status HTTP é 200, ou se o contrato da API foi mantido.

Se você quiser revisar os conceitos antes de executar os comandos, este guia de teste de carga de API cobre a base que o wrk coloca em prática.

Instalando o wrk

macOS

No macOS, use Homebrew:

brew install wrk
Enter fullscreen mode Exit fullscreen mode

No Apple Silicon, essa é a opção mais simples. Compilar manualmente pode gerar problemas com LuaJIT em ARM64, então o binário do Homebrew evita esse atrito.

Valide a instalação:

wrk --version
Enter fullscreen mode Exit fullscreen mode

Linux

Em distribuições baseadas em Debian/Ubuntu, instale as dependências:

sudo apt-get update
sudo apt-get install build-essential libssl-dev git -y
Enter fullscreen mode Exit fullscreen mode

Clone e compile o projeto:

git clone https://github.com/wg/wrk.git
cd wrk
make
Enter fullscreen mode Exit fullscreen mode

O binário wrk será gerado no diretório atual. Copie-o para o PATH:

sudo cp wrk /usr/local/bin
Enter fullscreen mode Exit fullscreen mode

Confirme:

wrk --version
Enter fullscreen mode Exit fullscreen mode

Executando o primeiro benchmark

A estrutura básica é:

wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
Enter fullscreen mode Exit fullscreen mode

As principais flags são:

  • -t ou --threads: número de threads do sistema operacional usadas pelo wrk.
  • -c ou --connections: número total de conexões HTTP abertas.
  • -d ou --duration: duração do teste, como 30s, 2m ou 2h.

Exemplo prático para uma API local:

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Esse comando executa:

  • 8 threads
  • 200 conexões simultâneas
  • 30 segundos de teste
  • relatório de percentis de latência com --latency

Use --latency quase sempre. A média esconde problemas de cauda, e a cauda costuma ser onde os usuários sentem degradação.

Outra flag útil é --timeout:

wrk -t8 -c200 -d30s --latency --timeout 2s http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Com --timeout 2s, qualquer requisição sem resposta em até 2 segundos é registrada como timeout.

Lendo a saída do wrk

Exemplo de saída:

Running 5s test @ http://10.135.232.163:3000
  2 threads and 5 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.82ms    2.64ms  26.68ms   85.81%
    Req/Sec   550.90    202.40     0.98k    68.00%
  5494 requests in 5.01s, 1.05MB read
Requests/sec:   1096.54
Transfer/sec:    215.24KB
Enter fullscreen mode Exit fullscreen mode

Leia primeiro as duas últimas linhas.

Requests/sec

É o throughput médio:

Requests/sec:   1096.54
Enter fullscreen mode Exit fullscreen mode

Neste caso, o servidor processou cerca de 1.096 requisições por segundo.

Use esse número para comparar:

  • versões diferentes do código
  • configurações diferentes do servidor
  • tamanhos diferentes de instância
  • impacto de cache, banco de dados ou middleware

Transfer/sec

É a quantidade de dados transferidos por segundo:

Transfer/sec:    215.24KB
Enter fullscreen mode Exit fullscreen mode

Esse número é mais importante quando:

  • o payload é grande
  • você suspeita de limite de rede
  • a resposta inclui arquivos, imagens ou grandes documentos JSON

Thread Stats

A tabela mostra a distribuição por thread:

Thread Stats   Avg      Stdev     Max   +/- Stdev
  Latency     3.82ms    2.64ms  26.68ms   85.81%
  Req/Sec   550.90    202.40     0.98k    68.00%
Enter fullscreen mode Exit fullscreen mode

Na linha de latência:

  • Avg: latência média
  • Stdev: desvio padrão
  • Max: maior latência observada
  • +/- Stdev: porcentagem de amostras dentro de um desvio padrão

Se Max estiver muito acima da média, você tem requisições lentas ocasionais. Isso pode indicar gargalos em banco de dados, garbage collection, filas, locks ou saturação de CPU.

Usando percentis de latência

Com --latency, o wrk imprime percentis:

Latency Distribution
   50%    3.21ms
   75%    4.86ms
   90%    7.09ms
   99%   14.13ms
Enter fullscreen mode Exit fullscreen mode

Interprete assim:

  • 50%: metade das requisições terminou em até 3.21ms
  • 90%: 90% terminaram em até 7.09ms
  • 99%: 99% terminaram em até 14.13ms

O p99 é crítico. Uma média de 3.82ms parece ótima, mas se o p99 cresce muito, uma parcela real dos usuários está tendo uma experiência pior.

Para benchmarks úteis, acompanhe pelo menos:

  • média
  • p90
  • p99
  • throughput
  • timeouts
  • erros no servidor

Testando POST com corpo JSON

Por padrão, o wrk envia requisições GET. Para enviar POST, corpo ou headers personalizados, use um script Lua.

Crie um arquivo post.lua:

wrk.method = "POST"
wrk.body   = '{"name": "Ada", "role": "engineer"}'
wrk.headers["Content-Type"] = "application/json"
Enter fullscreen mode Exit fullscreen mode

Execute:

wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Esse comando envia requisições POST com payload JSON para /api/users.

Para formulário application/x-www-form-urlencoded:

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
Enter fullscreen mode Exit fullscreen mode

Execute da mesma forma:

wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/form
Enter fullscreen mode Exit fullscreen mode

Enviando headers personalizados

Para casos simples, use -H:

wrk -t4 -c100 -d30s \
  -H "Authorization: Bearer TOKEN123" \
  --latency \
  http://localhost:3000/api/protected
Enter fullscreen mode Exit fullscreen mode

Com múltiplos headers:

wrk -t4 -c100 -d30s \
  -H "Authorization: Bearer TOKEN123" \
  -H "X-Tenant-Id: tenant_123" \
  --latency \
  http://localhost:3000/api/protected
Enter fullscreen mode Exit fullscreen mode

Regra prática:

  • use -H para headers simples
  • use Lua para método HTTP, corpo ou lógica por requisição

Como escolher threads e conexões

Comece com uma thread por núcleo de CPU na máquina que executa o wrk.

Exemplo: se sua máquina tem 8 núcleos:

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Depois, aumente conexões gradualmente:

wrk -t8 -c50  -d30s --latency http://localhost:3000/api/users
wrk -t8 -c100 -d30s --latency http://localhost:3000/api/users
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
wrk -t8 -c400 -d30s --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Observe quando:

  • Requests/sec para de subir
  • p99 aumenta muito
  • timeouts aparecem
  • CPU do servidor chega perto do limite
  • CPU da máquina cliente também satura

Se o cliente que roda o wrk estiver no limite de CPU, o gargalo pode ser o gerador de carga, não a API.

Exemplo de rotina de benchmark

Uma sequência simples para medir um endpoint:

# 1. Teste rápido
wrk -t4 -c50 -d10s --latency http://localhost:3000/api/users

# 2. Concorrência moderada
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users

# 3. Carga mais alta
wrk -t8 -c500 -d60s --latency --timeout 2s http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Durante os testes, monitore o servidor:

top
Enter fullscreen mode Exit fullscreen mode

ou:

htop
Enter fullscreen mode Exit fullscreen mode

Também acompanhe logs da aplicação, banco de dados e métricas de infraestrutura. O wrk mostra o sintoma; o diagnóstico normalmente vem de métricas do servidor.

Limites: wrk não valida correção

O wrk mede velocidade. Ele não valida comportamento.

Se um endpoint retornar HTTP 500 rapidamente em todas as requisições, o wrk ainda pode mostrar um ótimo Requests/sec. Isso acontece porque ele conta trocas HTTP concluídas, não respostas corretas.

Ele não verifica:

  • código de status esperado
  • campos obrigatórios no JSON
  • schema da resposta
  • regras de negócio
  • consistência entre chamadas
  • contrato da API

Por isso, não confie em benchmark de um endpoint que ainda não passou por testes funcionais.

O fluxo correto é:

  1. validar que a API funciona corretamente
  2. executar benchmark de carga
  3. comparar throughput, latência e erros
  4. repetir após mudanças relevantes

Equipes normalmente combinam uma ferramenta de benchmark com um conjunto de testes funcionais. Uma camada valida comportamento. A outra mede desempenho.

Onde o Apidog entra no fluxo

Um fluxo limpo tem duas camadas.

1. Validar comportamento

Antes de medir velocidade, confirme que o endpoint está correto.

No Apidog, você cria cenários que enviam requisições reais e validam:

  • status HTTP
  • campos JSON
  • schema de resposta
  • dados entre etapas
  • regras de negócio
  • ambientes diferentes

Essa é a camada que detecta o 500, o campo ausente ou a resposta fora do contrato.

2. Medir throughput e latência

Depois que o comportamento está validado, execute wrk contra os mesmos endpoints para medir concorrência e carga sustentada.

Se quiser manter testes funcionais e de carga no mesmo lugar, o Apidog também possui testes de desempenho integrados. Ainda assim, o wrk continua sendo uma excelente opção dedicada para benchmarks rápidos via linha de comando.

Executando testes funcionais do Apidog na CI

A camada funcional deve rodar na CI, não apenas no seu laptop.

Instale a CLI do Apidog:

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

Onde:

  • -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 se integra bem com sistemas de CI para marcar a execução como sucesso ou falha.

Para execução orientada por dados, use -d ou --iteration-data:

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

A CLI executa cenários e suítes Apidog salvos. Ela é headless, não é um cliente interativo de requisições e não é um gerador de carga.

Pense assim:

  • Apidog CLI: portão de correção
  • wrk: medidor de velocidade

Execute o portão de correção no pipeline. Depois, use wrk quando precisar medir throughput e latência.

Para configurar isso na prática, veja o tutorial de CI/CD da CLI do Apidog, o guia do GitHub Actions e a referência completa da CLI.

Checklist prático

Antes de confiar nos números do wrk, valide:

  • [ ] O endpoint passa nos testes funcionais
  • [ ] O ambiente de teste é conhecido
  • [ ] O banco de dados está em condição realista
  • [ ] Caches estão no estado esperado
  • [ ] Logs do servidor não mostram erros
  • [ ] A máquina cliente não está saturada
  • [ ] Você está medindo p90 e p99, não só média
  • [ ] O teste roda por tempo suficiente para estabilizar
  • [ ] Você salvou o comando usado para repetir depois

Exemplo de comando base para repetir em mudanças futuras:

wrk -t8 -c200 -d30s --latency --timeout 2s http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

FAQ

Qual a diferença entre wrk e ab, o ApacheBench?

Ambos geram carga HTTP e reportam requisições por segundo.

A diferença prática é que o wrk é multi-threaded e usa um loop de eventos, então costuma gerar mais carga a partir de uma única máquina e lidar melhor com alta concorrência.

O ab é single-threaded. Para cargas pesadas em uma única máquina, o wrk geralmente escala melhor.

Nenhum dos dois valida a correção da resposta.

Quantas threads e conexões devo usar?

Comece com uma thread por núcleo de CPU e ajuste as conexões para o nível de concorrência desejado.

Exemplo para uma máquina com 8 núcleos e 200 clientes concorrentes:

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Depois, aumente -c até o throughput parar de subir ou a latência de cauda crescer demais.

O wrk testa endpoints HTTPS?

Sim. Use uma URL https://:

wrk -t8 -c200 -d30s --latency https://api.example.com/users
Enter fullscreen mode Exit fullscreen mode

O TLS adiciona custo de CPU no cliente e no servidor, então o throughput bruto pode ser menor do que em HTTP puro.

O wrk valida o corpo da resposta ou o status HTTP?

Não. O wrk mede trocas HTTP concluídas e tempo de resposta.

Ele não valida status, JSON, schema ou regra de negócio. Para isso, use testes funcionais, como cenários executados pela CLI do Apidog, e depois use wrk para medir throughput.

Por quanto tempo devo executar um teste de carga?

Para verificação rápida, alguns segundos ajudam.

Para números mais confiáveis, use pelo menos 30 segundos:

wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Para investigar degradação gradual, aumente para alguns minutos:

wrk -t8 -c200 -d2m --latency http://localhost:3000/api/users
Enter fullscreen mode Exit fullscreen mode

Testes mais longos ajudam a revelar efeitos como caches, aquecimento, garbage collection, filas e vazamentos lentos.

Top comments (0)