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?
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
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
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
Clone e compile o projeto:
git clone https://github.com/wg/wrk.git
cd wrk
make
O binário wrk será gerado no diretório atual. Copie-o para o PATH:
sudo cp wrk /usr/local/bin
Confirme:
wrk --version
Executando o primeiro benchmark
A estrutura básica é:
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
As principais flags são:
-
-tou--threads: número de threads do sistema operacional usadas pelowrk. -
-cou--connections: número total de conexões HTTP abertas. -
-dou--duration: duração do teste, como30s,2mou2h.
Exemplo prático para uma API local:
wrk -t8 -c200 -d30s --latency http://localhost:3000/api/users
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
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
Leia primeiro as duas últimas linhas.
Requests/sec
É o throughput médio:
Requests/sec: 1096.54
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
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%
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
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"
Execute:
wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/users
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"
Execute da mesma forma:
wrk -t4 -c100 -d30s -s post.lua --latency http://localhost:3000/api/form
Enviando headers personalizados
Para casos simples, use -H:
wrk -t4 -c100 -d30s \
-H "Authorization: Bearer TOKEN123" \
--latency \
http://localhost:3000/api/protected
Com múltiplos headers:
wrk -t4 -c100 -d30s \
-H "Authorization: Bearer TOKEN123" \
-H "X-Tenant-Id: tenant_123" \
--latency \
http://localhost:3000/api/protected
Regra prática:
- use
-Hpara 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
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
Observe quando:
-
Requests/secpara 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
Durante os testes, monitore o servidor:
top
ou:
htop
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 é:
- validar que a API funciona corretamente
- executar benchmark de carga
- comparar throughput, latência e erros
- 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
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
Onde:
-
-t: ID do cenário, pasta ou suíte -
-e: ID do ambiente -
-r: formatos de relatório, comocli,html,jsonejunit
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
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
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
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
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
Para investigar degradação gradual, aumente para alguns minutos:
wrk -t8 -c200 -d2m --latency http://localhost:3000/api/users
Testes mais longos ajudam a revelar efeitos como caches, aquecimento, garbage collection, filas e vazamentos lentos.
Top comments (0)