Entendendo carga positiva e negativa em testes de performance
Muita gente confunde carga positiva e negativa com simplesmente testar mais usuários e testar menos. Não é bem assim. Carga positiva é quando você empurra o sistema além do que ele foi projetado para suportar. Carga negativa é quando você simula condições adversas — rede instável, recursos escassos, dados malformados — e observa como o sistema reage. Ambas são necessárias. A maioria dos times faz só a primeira e depois se pergunta por que a aplicação caiu num segundo de tráfego normal.
O que você precisa saber sobre carga positiva e negativa
Na prática, carga positiva significa aumentar gradualmente o volume de requisições até o sistema falhar. O ponto de ruptura é o dado mais importante que você vai coletar. Já a carga negativa envolve reduzir recursos disponíveis ou introduzir falhas controladas para ver se o sistema se degrada de forma Graceful. É diferente de apenas submeter dados errados. Envolver variáveis como latência de rede, conexões simultâneas excedentes, timeouts agressivos e disponibilidade parcial de dependências externas. Eu já vi equipes inteiras gastarem semanas configurando cenários de carga positiva com ferramentas como k6 e JMeter, sem nunca rodar um teste de carga negativa. O resultado costuma ser: o sistema aguenta 10.000 requisições por segundo quando tudo está perfeito, mas entra em colapso quando um microserviço retorna 503 e o circuito de fallback não foi preparado adequadamente.
Como configurar testes de carga positiva
Você precisa primeiro definir o baseline. Qual é o throughput normal do sistema? Quantas requisições por segundo ele processa sob condições normais? Sem esse número, você não sabe quanto é "muito". Use uma ferramenta como o locust ou o k6 para gerar tráfego progressivo. A estratégia de ramp-up mais comum é aumentar 10% a cada ciclo de dois minutos, observando métricas de latência, erro rate e utilização de CPU em cada incremento. O erro mais frequente é configurar muitos usuários virtuais de uma vez. Se você pular direto para 5.000 VUs e o sistema cair, não terá dado nenhuma informação útil sobre onde exatamente a ruptura aconteceu. A curva de falha é o dado, não apenas o número final de VUs suportadas.
Outro ponto que as pessoas ignoram: a carga positiva não testa só o seu código. Testa também a infraestrutura. Já vi o banco de PostgreSQL travar com pool de conexões esgotado enquanto o servidor de aplicação ainda tinha CPU disponível. O gargalo estava no database connection string com max_connections configurado para 100 e o app tentando abrir 300 conexões simultâneas. Isso só aparece em carga positiva bem calibrada.
Como configurar testes de carga negativa
Para carga negativa, o foco é outro. Você não quer saber quantas requisições o sistema aguenta. Quer saber o que acontece quando ele não aguenta. Introduza falhas de forma controlada. Um método simples: configure um service mesh ou um proxy como o Envoy para injetar delay aleatório de 500ms a 3 segundos nas respostas dos serviços downstream. Depois, observe o comportamento do circuit breaker e do retry policy do seu serviço principal. Isso revela se o seu sistema tem fallback adequado ou se apenas propaga a falha em cascata.
Outro cenário comum é restringir a memória disponível do contêiner em 50% do que ele usa normalmente em produção. Você vai ver o garbage collector trabalhando em regimes extremos, a latência disparando de forma não linear, e provavelmente OOM kills acontecendo de forma imprevisível. Anote esses pontos de inflexão. Eles são mais valiosos do que qualquer throughput number. Eu tive um problema específico com um sistema de filas RabbitMQ que, sob carga negativa com produtores falhando intermitentemente, criava millions de mensagens dead-lettered em segundos. O sistema de monitoramento não detectava porque os Letter queues estavam separadas do dashboard principal. A workaround foi criar um alertador customizado que monitorava o tamanho da DLQ com threshold de 1.000 mensagens em 60 segundos, e não apenas o status de connected/disconnected do broker.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Pitfalls comuns que iniciantes cometem
O primeiro é acreditar que carga positiva e negativa substituem testes de integração. Elas não substituem. Um teste de carga bem executado mostra que o sistema cai sob stress, mas não mostra qual endpoint específico falhou primeiro. Para isso, você precisa de logs estruturados com trace IDs e distributed tracing. Sem isso, você gasta horas investigando um slowdown que poderia ter sido identificado em minutos com Jaeger ou Datadog APM. O segundo pitfall é ignorar o efeito de warm-up. Benchmarks mostram resultados muito melhores do que a realidade porque o sistema estava aquecido. A primeira onda de tráfego consome ciclos para inicializar caches, compilar rotas JIT, e estabelecer conexões com o banco. Descarte os primeiros 30 segundos de qualquer execução de teste. Os dados são distorcidos.
O terceiro erro é usar dados sintéticos idênticos para todas as requisições. Sistemas reais processam dados variados. Queries com parâmetros diferentes geram planos de execução diferentes no banco. Caches são preenchidos de forma desigual. Se você usar o mesmo payload exato 10.000 vezes, vai obter resultados que não refletem nada do comportamento em produção. Varie os inputs. Use profiles realistas.
Quando carga positiva e negativa não funcionam
Existem cenários onde esses testes simplesmente não aplicam. Sistemas event-driven com processamento assíncrono massivo exigem testes de backpressure, não apenas de throughput. Se o seu sistema consome de múltiplos Kafka topics e processa eventos em lotes, simular 10.000 requisições HTTP não vai revelar problemas de consumidores sobrecarregados ou de lag de partition. Também não adianta testar carga em sistemas que dependem de APIs terceiras com limites rígidos. Se o seu backend chama um gateway de pagamento que permite 100 requisições por minuto, você pode gerar milhões de requests localmente, mas o teste será irrelevant porque o gargalo está fora do seu controle. Nesses casos, a estratégia correta é usar mock servers com rate limiting configurado para simular o comportamento real do provedor externo.
Finalmente, carga positiva e negativa não capturam problemas de segurança. Um sistema pode aguentar perfeitamente 50.000 conexões simultâneas e ainda assim ser vulnerável a SSRF, injection, ou abuse de funcionalidades legítimas. Ferramentas de teste de carga não substituem testes de penetração. Use ambas as abordagens de forma complementar.
Recursos práticos para começar
Para carga positiva, o k6 é mais simples de aprender do que o JMeter e produz métricas nativas em formatos que integram com Grafana e Prometheus. O script básico leva menos de 50 linhas. Para carga negativa, combine k6 com o k6 cloud ou use uma abordagem manual com tc (traffic control) no Linux para injetar latência e perda de pacotes de forma programática. Existe também o framework Gremlin que permite orquestrar falhas em ambientes cloud de forma segura e rastreável. É pago, mas se você roda testes de carga negativa com frequência, o custo é justificado pela reprodutibilidade dos cenários. Alternativa gratuita é usar o Chaos Monkey do Netflix adaptado para Kubernetes com o kube-monkey.
A parte mais importante não é a ferramenta. É a disciplina de documentar cada execução: configuração, baseline, pico de carga, ponto de ruptura, tempo de recuperação, e o que foi diferente em relação ao teste anterior. Sem registro consistente, você repete os mesmos erros depois sem perceber.