E se um serviço ficar lento agora? A pergunta importante não é se falhas vão acontecer, mas se a arquitetura consegue absorvê-las sem transformar um problema pequeno em uma indisponibilidade geral.
Introdução: por que provocar falhas de propósito?
Em sistemas distribuídos, uma aplicação pode funcionar perfeitamente em condições normais e ainda assim falhar quando uma dependência fica lenta, uma instância desaparece ou uma conexão com o banco de dados é interrompida. Isso acontece porque os serviços não trabalham isoladamente: filas, redes, APIs, caches e bancos de dados criam relações que podem amplificar uma falha inicial.
Chaos Engineering, ou engenharia do caos, é a prática de realizar experimentos controlados para descobrir como um sistema se comporta diante de situações adversas. A ideia não é causar indisponibilidade por diversão, nem testar sem planejamento. É formular uma hipótese, introduzir uma falha limitada, observar o comportamento real e usar as evidências para melhorar a arquitetura. Os princípios da disciplina recomendam medir o estado normal do sistema, experimentar com eventos realistas e procurar diferenças entre o comportamento esperado e o comportamento observado [1].
Essa abordagem muda a mentalidade da equipe. Em vez de assumir que tudo deve funcionar sempre, partimos do princípio de que componentes podem falhar — e projetamos o sistema para limitar o impacto, continuar oferecendo funções essenciais e se recuperar com segurança.
Então, por que testar em staging ou até mesmo em produção? Testes em ambientes de homologação reduzem o risco inicial e são o ponto de partida recomendado. Com maturidade, controles e autorização, experimentos cuidadosamente delimitados em produção podem revelar comportamentos que não aparecem em ambientes artificiais, por exemplo, devido ao tráfego real e às dependências de verdade. Não se começa derrubando serviços críticos em produção: começa-se pequeno, com monitoramento, plano de interrupção e critérios objetivos para interromper o teste. A documentação do AWS Fault Injection Service também recomenda planejar o experimento e começar em ambiente de teste ou pré-produção [2].
O que é o ChaosEngineeringMasterDeck?
Neste projeto, o ChaosEngineeringMasterDeck é um catálogo versionado de experimentos de resiliência apresentado como um baralho de cartas. Cada carta descreve uma falha possível e transforma essa falha em um experimento repetível, com objetivo, limites, métricas e procedimento de recuperação.
O formato de baralho torna a prática mais acessível durante revisões de arquitetura, simulações de incidentes e dinâmicas de equipe. Uma carta pode ser sorteada em uma sessão de treinamento, mas sua execução não deve ser improvisada: ela precisa ter sido revisada, aprovada e preparada para o ambiente definido.
O Deck não substitui ferramentas de injeção de falhas, telemetria ou automação. Ele funciona como uma camada de padronização e governança sobre essas ferramentas, registrando por que o experimento existe, como será executado e quais evidências indicarão sucesso ou falha.
O que cada carta contém?
- Identificação e objetivo: nome, serviço-alvo, ambiente e risco que queremos investigar.
- Hipótese: o comportamento que esperamos observar depois de introduzir a falha.
- Estado estável (steady state): indicadores que descrevem o funcionamento normal para o usuário, como latência, taxa de erro e conclusão de operações importantes.
- Variável de caos: a condição que será alterada, como latência de rede, indisponibilidade de uma instância ou falha de conexão.
- Blast radius: limites explícitos sobre quais serviços, usuários, requisições e recursos poderão ser afetados.
- Observabilidade: painéis, logs, métricas, rastreamentos distribuídos e alertas que serão consultados.
- Critérios de abortagem e recuperação: condições para interromper o teste, como restaurar o serviço e como confirmar que tudo voltou ao normal.
- Resultado e aprendizado: evidências coletadas, lacunas identificadas e ações corretivas com responsáveis.
Esse modelo impede que a experiência se resuma a “derrubamos alguma coisa e vimos no que deu”. O experimento passa a ter uma hipótese que pode ser confirmada, refutada ou refinada.
Exemplo de uma carta do Deck
id: CE-004
nome: Latência elevada no serviço de recomendações
ambiente: staging
alvo: recommendation-service
falha:
tipo: latencia
atraso_adicional: 800ms
duracao: 5m
blast_radius:
trafego: usuarios-sinteticos
percentual_maximo: 10%
endpoint: /api/recommendations
hipotese: >
O catálogo continuará respondendo em até 500 ms no p95,
a taxa global de erros ficará abaixo de 1% e a compra
continuará funcionando mesmo sem recomendações personalizadas.
abortagem:
- taxa_global_de_erros_acima_de: 1%
- alerta_critico_disparado
- falha_no_fluxo_de_compra
Os valores do exemplo são parâmetros ilustrativos para o cenário deste artigo. Em uma aplicação real, limites e métricas precisam ser definidos a partir dos SLOs, dos dados históricos e do impacto aceitável para o negócio.
Estudo de caso: recomendações lentas, catálogo disponível
Imagine uma loja virtual implantada na AWS. A aplicação usa microsserviços Java com Spring Boot e executa tarefas em mais de uma zona de disponibilidade. O balanceador distribui as requisições, e a tela de produtos consulta dois serviços: o Catálogo, responsável pelos dados essenciais dos produtos, e o Recomendações, que personaliza sugestões com base no perfil do cliente.
A recomendação melhora a experiência, mas não é indispensável para consultar um produto ou concluir uma compra. Se esse serviço ficar lento, o sistema deve continuar útil: a página pode mostrar uma lista popular previamente armazenada em cache, em vez de manter a requisição inteira bloqueada.
1. Hipótese e estado estável
Antes do experimento, a equipe observa o sistema em condições normais e define o que significa “saudável” do ponto de vista do cliente. Para esta simulação didática, usaremos a seguinte linha de base:
| Indicador | Estado normal ilustrativo | Limite durante o experimento |
|---|---|---|
| Latência p95 do Catálogo | 210 ms | Até 500 ms |
| Taxa global de erros HTTP | 0,2% | Abaixo de 1% |
| Conclusão do fluxo de compra | 99,7% | Sem queda relevante atribuível ao teste |
| Fallback de recomendações | Não acionado normalmente | Deve assumir quando necessário |
A hipótese é: se adicionarmos 800 ms de latência ao serviço de recomendações por cinco minutos, o Catálogo continuará dentro do limite de latência, a taxa global de erros permanecerá abaixo de 1% e o fluxo de compra não será interrompido.
A hipótese é mensurável. Assim, a equipe não depende de impressões como “pareceu rápido” ou “ninguém percebeu nada”.
2. Execução controlada e Blast Radius
O experimento começa em staging, com dados de teste e geração de tráfego sintético. A falha é aplicada somente ao caminho de comunicação com o serviço de recomendações, por meio de um proxy de teste ou ferramenta de injeção de falhas. Apenas até 10% das requisições sintéticas entram nesse caminho, e a duração máxima é de cinco minutos.
Esse limite é o Blast Radius, ou raio de explosão: a área potencialmente afetada caso algo saia do previsto. Neste caso, ele exclui o serviço de pagamentos, o banco de dados de pedidos e o tráfego de clientes reais. O time também define antecipadamente quem pode iniciar o experimento, quem acompanha os painéis e quem pode encerrá-lo.
O teste é cancelado automaticamente ou manualmente se a taxa global de erros superar 1%, se o fluxo de compra falhar ou se um alerta crítico for acionado. Ao terminar, a injeção de latência é removida e a equipe verifica a recuperação. Esses limites são essenciais porque ferramentas como o AWS Fault Injection Service executam ações reais sobre recursos selecionados; por isso, a seleção dos alvos e os controles devem ser revisados antes da execução [2].
3. Quais padrões de resiliência esperamos observar?
Timeouts: a chamada ao serviço de recomendações tem um limite de espera. Sem timeout, uma chamada lenta poderia ocupar conexões e threads por tempo excessivo.
Circuit Breaker: quando as chamadas falham ou ultrapassam os limites configurados, o disjuntor abre temporariamente e impede novas chamadas repetidas ao serviço degradado. Isso reduz a chance de que uma dependência lenta consuma os recursos do restante da aplicação. Em projetos Spring Boot, bibliotecas como Resilience4j oferecem suporte a Circuit Breaker, Retry, Bulkhead e TimeLimiter [3].
Fallback: com o serviço de recomendações indisponível, a aplicação utiliza uma lista de produtos populares armazenada em cache. O fallback não deve fabricar resultados críticos nem declarar uma operação financeira como concluída; ele só substitui a funcionalidade opcional de personalização.
Bulkhead: limites de concorrência isolam os recursos usados pelas chamadas de recomendação, reduzindo o risco de que elas esgotem as threads ou conexões necessárias ao Catálogo.
Retries limitados: novas tentativas, quando necessárias, usam limite e intervalo de espera. Repetir chamadas indefinidamente pode amplificar uma falha e gerar uma tempestade de retries. Em uma dependência já lenta, pode ser melhor falhar rápido e acionar o fallback.
O escalonamento automático pode ajudar quando o problema é falta de capacidade, mas não corrige automaticamente toda falha. Se a causa for uma dependência travada, aumentar a quantidade de instâncias pode não resolver — e, em alguns casos, até aumentar a pressão sobre essa dependência.
4. Observabilidade: como sabemos se funcionou?
Durante o teste, o time acompanha um painel com métricas e sinais correlacionados:
- Métricas: latência p50/p95/p99, taxa de erros, volume de requisições, timeouts, estado do Circuit Breaker, uso de CPU e memória e taxa de acionamento do fallback.
- Logs estruturados: registros com identificador de correlação, para encontrar uma requisição ao longo dos serviços sem expor dados sensíveis.
- Rastreamento distribuído: traces para confirmar em qual dependência o tempo foi consumido e se o atraso se propagou ao Catálogo.
- Alertas: notificações sobre violações dos limites definidos e sinais de degradação do fluxo de compra.
A equipe deve monitorar tanto o serviço atingido quanto a experiência do usuário. Uma queda no consumo de CPU, por exemplo, não prova que o sistema está saudável: o serviço pode estar recusando requisições. Da mesma forma, a aplicação pode continuar respondendo com HTTP 200, mas entregar uma experiência lenta ou incompleta. Por isso, indicadores técnicos precisam estar ligados a resultados observáveis para o cliente. Os princípios de Chaos Engineering destacam latência, vazão e taxa de erros como medidas possíveis do estado estável [1].
5. Resultados ilustrativos da simulação
Como este artigo descreve um cenário didático, os números a seguir são resultados hipotéticos de referência, não medições de um experimento real:
| Indicador | Exemplo de resultado | Interpretação |
|---|---|---|
| Latência p95 do Catálogo | 285 ms | Abaixo do limite de 500 ms |
| Taxa global de erros HTTP | 0,6% | Abaixo do limite de 1% |
| Recomendações personalizadas | Degradadas durante a injeção | Falha isolada na funcionalidade opcional |
| Fallback | Acionado com sucesso | Página continuou oferecendo sugestões genéricas |
| Fluxo de compra | Sem interrupção atribuível ao teste | Função essencial preservada |
Nesse resultado ilustrativo, a hipótese seria aceita: a falha local não comprometeu o caminho crítico. Ainda assim, o teste não provaria que o sistema está preparado para todo tipo de incidente. Ele mostraria apenas que um tipo específico de latência, dentro dos limites definidos, foi absorvido de forma aceitável.
Caso os indicadores ultrapassassem os limites, isso não seria simplesmente um “teste fracassado”. Seria uma evidência útil: talvez o timeout estivesse alto demais, o Circuit Breaker abrisse tarde, o fallback dependesse da mesma infraestrutura degradada ou a concorrência das chamadas não estivesse isolada. A equipe registraria a descoberta, corrigiria a arquitetura e repetiria o mesmo experimento para confirmar a melhoria.
Como ampliar o Deck com segurança
Depois de validar experimentos menores, o catálogo pode incluir cartas para cenários mais amplos, como falha de conexão com o banco, indisponibilidade de uma instância, esgotamento de recursos ou perda de uma zona de disponibilidade. A AWS, por exemplo, documenta um cenário de interrupção de energia de uma Availability Zone para avaliar aplicações distribuídas em múltiplas zonas [4]. Esse tipo de teste tem raio de impacto muito maior e exige revisão específica de alvos, permissões, dependências, capacidade de recuperação e plano de interrupção.
Uma progressão sensata é:
- Começar em ambiente de teste, com um alvo e uma falha simples.
- Conferir observabilidade e abortagem antes de aumentar o alcance.
- Automatizar a execução e a coleta de resultados, evitando depender de memória individual.
- Repetir após mudanças relevantes, como alterações de arquitetura, infraestrutura ou bibliotecas de resiliência.
- Avançar para ambientes mais representativos gradualmente, incluindo produção somente quando houver maturidade operacional, autorização e limites seguros.
O Deck também deve guardar o que foi aprendido: hipótese inicial, configuração aplicada, horário, métricas antes/durante/depois, alarmes acionados, incidentes observados e ações corretivas. Assim, um resultado deixa de ser uma experiência isolada e passa a fortalecer o conhecimento coletivo da equipe.
Conclusão: resiliência se demonstra, não se presume
Nenhuma arquitetura distribuída elimina todas as falhas. O objetivo da engenharia de resiliência é evitar que uma falha localizada se transforme em um problema sistêmico, proteger os fluxos essenciais e recuperar o serviço dentro de limites aceitáveis.
O ChaosEngineeringMasterDeck organiza essa prática em experimentos repetíveis e compreensíveis: cada carta descreve uma hipótese, limita o Blast Radius, define métricas de controle e registra o aprendizado. No estudo de caso, a latência é aplicada a uma funcionalidade opcional para verificar se o Catálogo e o fluxo de compra continuam operando.
A principal lição é cultural: confiabilidade não é responsabilidade exclusiva de uma equipe de infraestrutura nem uma etapa realizada somente antes do lançamento. Desenvolvimento, operações, arquitetura e produto precisam compartilhar hipóteses, dados e decisões. Quando o caos é introduzido com método e segurança, ele deixa de ser apenas uma ameaça e se torna uma oportunidade de aprender — antes que uma falha real ensine a mesma lição aos clientes.
Referências
- Principles of Chaos Engineering. Fundamentos de estado estável, hipóteses, eventos realistas e minimização do Blast Radius. https://principlesofchaos.org/
- AWS — Planning your AWS FIS experiments. Recomendações para planejar experimentos, definir o estado estável, formular hipóteses e começar em ambientes de teste. https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html
- Resilience4j — Getting Started. Biblioteca de tolerância a falhas com Circuit Breaker, Retry, Bulkhead, Cache e TimeLimiter. https://resilience4j.readme.io/docs/getting-started
- AWS — AZ Availability: Power Interruption. Cenário para avaliar os efeitos de uma interrupção em uma zona de disponibilidade. https://docs.aws.amazon.com/fis/latest/userguide/az-availability-scenario.html
- Microsoft Azure Well-Architected Framework — Reliability testing strategy. Conceitos de resiliência, recuperação, injeção de falhas e testes de confiabilidade. https://learn.microsoft.com/en-us/azure/well-architected/reliability/reliability-test
Nota sobre o estudo de caso: a arquitetura e os resultados numéricos deste artigo são ilustrativos e foram incluídos para demonstrar como estruturar um experimento. Eles não representam uma execução real nem resultados observados em um ambiente de produção.
Top comments (0)