Um aplicativo pode funcionar perfeitamente durante desenvolvimento e ainda falhar completamente quando submetido ao comportamento real dos usuários.
O problema é que muitos times validam apenas o "happy path":
- usuário acessa a tela;
- API responde;
- banco retorna dados;
- processo termina com sucesso.
Mas sistemas reais enfrentam:
- milhares de usuários simultâneos;
- picos inesperados;
- integrações lentas;
- filas acumuladas;
- bancos disputados;
- memória crescendo continuamente;
- serviços externos indisponíveis.
A pergunta correta não é:
"Meu sistema funciona?"
Mas:
"Como meu sistema se comporta quando todos os componentes começam a ser pressionados ao mesmo tempo?"
É nesse cenário que entram os ambientes sandbox e os testes de estresse.
O que é um ambiente sandbox para testes de performance?
Um sandbox é uma réplica controlada do ambiente real onde podemos provocar situações extremas sem impactar usuários.
Ele deve representar:
- arquitetura semelhante à produção;
- mesmas integrações críticas;
- configuração próxima de infraestrutura;
- volume de dados compatível;
- mesmas regras de segurança.
Um erro comum é criar um ambiente completamente diferente e depois concluir:
"O teste passou, então estamos preparados."
Mas se o sandbox possui:
- banco menor;
- menos serviços;
- máquinas maiores;
- ausência de integrações;
- poucos dados;
o resultado não representa a realidade.
Antes de testar: entender o que você quer medir
Performance não é apenas medir tempo de resposta.
Existem diferentes dimensões.
Latência
Quanto tempo uma operação demora.
Exemplo:
GET /clientes
Tempo médio: 120ms
P95: 350ms
P99: 900ms
O usuário normalmente sente os extremos, não a média.
Uma API pode ter média excelente, mas possuir 1% das requisições demorando vários segundos.
Throughput
Quantidade de operações suportadas.
Exemplo:
500 requisições por segundo
1000 requisições por segundo
5000 requisições por segundo
O objetivo é descobrir:
Qual é o limite sustentável?
Concorrência
Quantidade de usuários executando ações simultaneamente.
Exemplo:
10 usuários 100 usuários 1.000 usuários 10.000 usuários
Muitos sistemas funcionam bem com usuários sequenciais, mas quebram quando existe competição por recursos.
Utilização de recursos
Avaliar:
- CPU;
- memória;
- disco;
- rede;
- conexões;
- threads;
- filas;
- cache.
Tipos de testes de performance
1. Load Test (teste de carga)
O objetivo é validar o comportamento esperado.
Exemplo:
Uma aplicação suporta:
- 5 mil usuários simultâneos;
- 300 requisições por segundo;
- checkout em menos de 2 segundos.
Criamos uma carga próxima dessa realidade.
2. Stress Test
Aqui começamos a ultrapassar os limites.
Exemplo:
500 usuários 1000 usuários 5000 usuários 10000 usuários
Até responder:
- onde começa a degradação?
- qual componente quebra primeiro?
- existe recuperação automática?
3. Spike Test
Simula picos repentinos.
Exemplo:
Um aplicativo de ingressos.
- Às 10h: 100 usuários
- Às 10h01: 50.000 usuários
Serve para validar:
- autoscaling;
- filas;
- cache;
- proteção contra avalanche.
4. Soak Test (teste prolongado)
Muitos problemas aparecem apenas depois de horas.
Exemplo: rodar por 24 horas, 48 horas ou 7 dias.
Encontrando problemas como:
- memory leak;
- conexões não liberadas;
- crescimento de logs;
- filas acumuladas.
Como montar um teste integrado realista?
O maior erro é testar apenas endpoints isolados.
Um sistema real é uma cadeia:
Usuário
↓
Frontend
↓
API Gateway
↓
BFF
↓
Microsserviços
↓
Banco
↓
Mensageria
↓
Serviços externos
O teste precisa reproduzir essa jornada.
Ferramentas para testes de carga
k6
Muito utilizado atualmente.
Exemplo:
import http from "k6/http";
import { check } from "k6";
export const options = {
vus: 100,
duration: "5m",
};
export default function () {
const response = http.get("https://api.exemplo.com/clientes");
check(response, {
"status 200": (r) => r.status === 200
});
}
Permite:
- testes versionados;
- integração CI/CD;
- métricas detalhadas.
JMeter
Muito utilizado em ambientes corporativos.
Bom para:
- SOAP;
- APIs REST;
- fluxos complexos;
- testes tradicionais.
Gatling
Muito utilizado em arquiteturas modernas.
Tem boa integração com:
- Scala;
- pipelines;
- aplicações distribuídas.
Locust
Interessante quando o time trabalha muito com Python.
Permite escrever cenários usando código.
Como gerar dados realistas?
Um teste ruim geralmente usa:
Cliente 1 Produto 1 Pedido 1
Mas produção possui:
10 milhões de clientes 500 mil produtos bilhões de registros
O banco muda completamente de comportamento.
Devemos gerar:
- dados distribuídos;
- diferentes tamanhos;
- casos raros;
- registros antigos;
- históricos grandes.
Exemplo:
Testar:
Buscar cliente por CPF
com:
100 registros
é completamente diferente de:
100 milhões de registros
Observabilidade durante o teste
Um teste sem observabilidade é apenas um gerador de tráfego.
Durante a execução devemos acompanhar:
Aplicação
- tempo de resposta;
- erros;
- exceções;
- filas internas.
Infraestrutura
Banco
- queries lentas;
- locks;
- conexões;
- índices.
Mensageria
- tamanho das filas;
- tempo de processamento;
- consumidores ativos.
Testando pontos críticos
Banco de dados
Perguntas importantes:
- Existem índices adequados?
- Existem queries N+1?
- Existem locks?
- Existe paginação?
Um endpoint simples pode derrubar uma aplicação:
SELECT *
FROM pedidos
ORDER BY created_at DESC;
Se existir milhões de registros.
Cache
Testar:
- cache hit;
- cache miss;
- invalidação;
- expiração.
Um sistema pode funcionar enquanto o cache existe e falhar quando ele expira.
APIs externas
Simular:
- timeout;
- indisponibilidade;
- respostas lentas.
Exemplo:
- Pagamento demora: 200ms normalmente e 10 segundos em cenário extremo. Como seu sistema reage?
Estratégia profissional de teste
Uma abordagem madura:
Etapa 1 — Baseline
Descobrir comportamento normal.
Exemplo:
100 usuários
P95: 300ms
Erro: 0%
Etapa 2 — Crescimento gradual
Aumentar:
100 500 1000 5000 10000 usuários
Observar o ponto de ruptura.
Etapa 3 — Encontrar gargalo
Perguntar:
"O primeiro componente que falhou foi qual?"
Pode ser:
- banco;
- API;
- infraestrutura;
- serviço externo;
- arquitetura.
Etapa 4 — Otimizar
Aplicar:
- cache;
- índices;
- filas;
- processamento assíncrono;
- escalabilidade horizontal;
- redução de payload.
Etapa 5 — Repetir
Performance é um ciclo.
Medir -> Encontrar gargalo -> Corrigir -> Medir novamente
Pontos de atenção que poucos consideram
Não testar somente o cenário perfeito
Teste:
- usuário abandonando fluxo;
- requisição duplicada;
- falha parcial;
- dados inconsistentes.
Não confundir escala vertical com arquitetura preparada
Adicionar máquina maior resolve até certo ponto.
Mas servidor maior não resolve:
- Query ruim
- Arquitetura bloqueante
- Falta de cache
- Processamento síncrono excessivo
Cuidado com testes destrutivos
Nunca executar stress test sem:
- limites;
- monitoramento;
- plano de parada.
Um teste mal planejado pode derrubar:
- banco;
- filas;
- serviços compartilhados.
Construindo um ambiente sandbox isolado para testes de performance
Antes de executar qualquer teste de carga ou estresse, é necessário criar um ambiente onde seja possível reproduzir comportamentos extremos sem comprometer usuários reais.
O objetivo do sandbox é funcionar como um laboratório controlado, permitindo alterar configurações, aumentar consumo de recursos, simular falhas e repetir experimentos até encontrar os limites da aplicação.
O que esse ambiente precisa reproduzir?
Um sandbox eficiente não precisa necessariamente ter o mesmo tamanho da produção, mas deve preservar os mesmos comportamentos arquiteturais:
- mesma aplicação;
- mesmas dependências;
- mesmas integrações críticas;
- configuração semelhante de rede;
- banco com volume representativo;
- mecanismos de cache;
- filas e processamento assíncrono;
- ferramentas de observabilidade.
Estratégias para criar o ambiente controlado
1. Máquina virtual (VM)
Uma das formas mais simples de criar isolamento.
Exemplos:
- VirtualBox;
- VMware;
- Hyper-V;
- Proxmox.
A ideia é criar uma máquina dedicada para testes.
Vantagens:
- isolamento completo;
- fácil restauração por snapshot;
- ambiente reproduzível;
- possibilidade de limitar CPU e memória.
Configuração:
CPU: 4 cores RAM: 16GB SSD: 100GB
Docker instalado
Containers:
- API
- Banco
- Redis
- Prometheus
- Grafana
Containers com Docker
Para aplicações modernas, normalmente é a opção mais prática.
Em vez de criar máquinas completas, criamos ambientes isolados por serviço.
Exemplo:
# docker-compose.yml
services:
api:
image: app-api
database:
image: postgres
redis:
image: redis
monitoring:
image: grafana
Benefícios:
- ambiente versionado;
- reprodução rápida;
- fácil automação;
- integração com CI/CD.
Ambiente Kubernetes dedicado
Para arquiteturas maiores:
Kubernetes Sandbox Cluster
Namespace: | |-- frontend |-- api |-- workers |-- databases |-- monitoring
Permite testar:
- escalabilidade horizontal;
- autoscaling;
- limites de recursos;
- comportamento distribuído.
Exemplo:
CPU limit: 500m
Memory: 1GB
Replicas: 3 -> 20
Preparando o sandbox para testes extremos
Depois de criar o ambiente, o próximo passo é controlar as variáveis.
Limitar recursos propositalmente
Um erro comum é criar um ambiente maior que produção.
Exemplo:
Produção:
API: 4 CPUs 8GB RAM
Sandbox:
API: 8 CPUs 32GB RAM
O teste nunca encontrará gargalos.
O ideal é criar cenários:
Cenário normal
4 CPUs 8GB RAM
Cenário limitado
2 CPUs 4GB RAM
Cenário extremo
1 CPU 2GB RAM
Isso ajuda a entender:
- quando começa degradação;
- como a aplicação reage;
- quais componentes são críticos.
Criando dados realistas
O ambiente precisa ter dados próximos da realidade.
Não basta criar:
100 usuários 10 pedidos 5 produtos
Quando produção possui:
10 milhões usuários 500 milhões registros
Devemos considerar:
- volume;
- distribuição;
- histórico;
- relacionamentos;
- índices.
Exemplo:
Banco preparado:
Clientes ├── 5 milhões registros
Pedidos ├── 100 milhões registros
Transações ├── 500 milhões registros
Simulando dependências externas
Em testes de estresse, integrações externas podem prejudicar a análise.
Exemplo:
Pagamento:
Aplicação | | API Banco Externo
Se o fornecedor estiver lento, você não sabe se o problema está na aplicação.
Soluções:
- mocks;
- simuladores;
- ambientes sandbox;
- serviços fake.
Exemplo:
Pagamento real
ou
Mock Payment API | | Latência configurável: 200ms 500ms 5s
Controle e observabilidade do experimento
Todo teste deve responder:
"o que aconteceu?"
Por isso o sandbox precisa possuir:
Métricas
- CPU;
- memória;
- rede;
- latência;
- throughput.
Logs
Tracing
Exemplo:
Request
200ms API Gateway
500ms Serviço Pedido
5s Banco
100ms Cache
Sem isso, você sabe que ficou lento, mas não sabe por quê.
Executando o primeiro teste controlado
Uma estratégia:
1. Baseline
Executar com pouca carga:
10 usuários
P95: 300ms
2. Aumentar gradualmente
100 usuários
500 usuários
1000 usuários
5000 usuários
3. Registrar o ponto de degradação
Exemplo:
Até 2000 usuários: OK
3000 usuários: latência aumenta
5000 usuários: erros começam
Esse é o limite conhecido.
Um sandbox eficiente transforma testes de performance em experimentos controlados.
Em vez de esperar que a produção revele seus problemas, criamos um ambiente onde podemos provocar:
- alta concorrência;
- falta de recursos;
- lentidão;
- falhas;
- picos inesperados.
A principal vantagem não é apenas descobrir "quantos usuários o sistema suporta", mas entender como ele se comporta quando começa a falhar e quais decisões arquiteturais precisam ser tomadas antes disso acontecer.
Conclusão
A engenharia de performance não começa quando o sistema está lento. Ela começa quando ainda existe capacidade de provocar falhas de forma segura.
Um bom time não pergunta apenas:
"Quantos usuários meu sistema suporta?"
Ele responde:
- qual é o limite?
- onde quebra?
- como recupera?
- quais métricas indicam degradação?
- qual componente precisa evoluir?
O ambiente sandbox é justamente o laboratório onde conseguimos transformar suposições em evidências. Porque sistemas robustos não são aqueles que nunca falham. São aqueles que conhecem seus limites antes que os usuários descubram.
Referências
1. Site Reliability Engineering (SRE) — Google
Site Reliability Engineering
Referência fundamental para entender:
- limites de sistemas distribuídos;
- capacidade e escalabilidade;
- monitoramento;
- SLIs/SLOs;
- gestão de incidentes;
- testes de resiliência.
https://sre.google/sre-book/table-of-contents/
2. The Site Reliability Workbook — Google
The Site Reliability Workbook
Mais prático que o primeiro livro.
Aborda:
- implementação de práticas SRE;
- testes de carga;
- observabilidade;
- automação;
- engenharia de confiabilidade.
https://sre.google/workbook/table-of-contents/
3. Release It! — Michael Nygard
Release It!
Um dos livros mais importantes sobre sistemas em produção.
Explora:
- cascatas de falhas;
- circuit breaker;
- timeout;
- bulkhead;
- estabilidade de sistemas distribuídos.
Conceitos muito aplicáveis a:
- APIs;
- microsserviços;
- integrações externas.
4. Designing Data-Intensive Applications — Martin Kleppmann
Designing Data-Intensive Applications
Excelente para entender:
- gargalos de dados;
- bancos distribuídos;
- replicação;
- filas;
- consistência;
- escalabilidade.