Publicado em

Abrace o caos

Troque a pergunta "como eu impeço isso de quebrar?" por "o que eu faço quando isso quebrar?", porque a brecha que você não viu é estrutural, não falha da sua análise.

Em

Tags

Quantas vezes você já tentou prevenir um problema? Quantas vezes mapeou todos os jeitos possíveis de algo dar errado, só para o único cenário que você deixou passar causar o maior estrago?

Para quem, como eu, já tentou construir o sistema perfeito, aquele que antecipava toda falha antes dela acontecer, eu tenho uma má notícia.

As coisas vão quebrar.

Erros vão acontecer, serviços vão cair, dados vão ser apagados, alguém vai furar o SLA que prometeu para você. Gostando ou não.

A gente da tecnologia, quando está construindo algo, tende a tentar vedar todo caminho possível que um problema poderia tomar. O que esquecemos de medir é o esforço que queimamos nessa caçada impossível de fechar toda brecha. Por mais completa que seja sua análise inicial, alguma coisa não vai estar coberta.

Obviamente, quando há vidas humanas em jogo, mandar alguém para o espaço, operar um equipamento cirúrgico assistido por computador, precisão máxima não se negocia. Mas para quase todo o resto que construímos, a postura correta é assumir que problemas vão acontecer.

Isso significa abandonar testes, revisões, checklists? Não é isso que estou dizendo. O que estou dizendo é que não devemos ficar paranoicos em sempre resolver a causa de um problema antes que ele exista.

Mas se não vamos passar a vida prevendo toda falha, como manter o sistema inteiro e funcionando enquanto os problemas continuam acontecendo?

ABRACE O CAOS

Abraçar o caos significa aceitar a incerteza das coisas e seguir em frente. Significa trocar a pergunta “como eu impeço isso de quebrar?” pela pergunta “o que eu faço quando isso quebrar?”.

Isso não é um slogan. É uma postura com nome, teoria e prática documentada por trás.

O nome técnico do problema

Aquele “cenário não identificado” que você tentou prever e não conseguiu tem um nome formal: o Cisne Negro. Nassim Taleb o define assim em O Cisne Negro: um evento fora da curva que nada no passado apontava, de impacto extremo, e que só parece óbvio e previsível depois que acontece, porque nosso cérebro é bom demais em inventar explicações retroativas (a falácia narrativa).

Do ponto de vista do peru, não ser alimentado no dia mil e um é um Cisne Negro. Para o açougueiro, não é. Ele sempre soube o que vinha. O problema é que na maioria dos sistemas que construímos, nós somos o peru: não temos acesso ao ponto de vista do açougueiro, e fingir que temos é exatamente o que produz arquiteturas confiantes demais que desabam do nada.

A resposta de Taleb não é “preveja melhor”. É aceitar que você não vai prever, e organizar o sistema para ser robusto ao desconhecido: redundância, opcionalidade, exposição em barbell (segurança extrema de um lado, risco calculado do outro, sem meio-termo frágil).

Em Antifrágil, ele empurra a ideia um passo adiante: são três categorias, não duas. O frágil quebra sob choque. O robusto aguenta o choque e permanece indiferente. O antifrágil melhora sob choque. Nas palavras dele, o frágil quer tranquilidade, o antifrágil cresce a partir da desordem, e o robusto não liga muito.

Isso muda a pergunta com que este texto começou. Não é “como eu construo o sistema perfeito”. É “como eu construo um sistema que sai mais forte, e não mais frágil, depois de quebrar”.

Por que prever tudo é estruturalmente impossível

Isso não é falta de esforço da sua parte. É estrutural.

Leslie Lamport capturou isso numa frase que Roberto Vitillo retoma em Understanding Distributed Systems: um sistema distribuído é aquele em que a falha de um computador que você nem sabia que existia pode tornar o seu próprio computador inutilizável.

Qualquer sistema moderno real, com filas, caches, serviços de terceiros, réplicas, DNS, um provedor de nuvem, contém componentes que você não projetou, não controla e, em muitos casos, nem sabe que estão na sua cadeia de dependências. A “brecha não coberta” que te assombra não é um buraco na sua análise. É um componente fora do seu campo de visão por definição.

Martin Kleppmann, em Designing Data-Intensive Applications, formaliza a distinção que separa quem entendeu isso de quem ainda tenta construir o sistema perfeito: uma fault é um componente desviando do que deveria fazer, uma failure é o sistema inteiro deixando de servir o usuário. Um sistema tolerante a falhas é aquele que absorve faults sem transformá-las em failures.

E a consequência prática mais contraintuitiva dessa ideia é que Kleppmann defende provocar falhas de propósito. É a filosofia por trás do Chaos Monkey, a ferramenta que a Netflix soltou dentro da própria infraestrutura de produção para matar instâncias aleatoriamente, de forma contínua, em vez de esperar a falha real chegar sem avisar.

Você não escreve testes para provar que o problema não vai acontecer. Você escreve testes, e sistemas, que assumem que vai. E que provocam o problema cedo, com você olhando, em vez de tarde, com o cliente olhando.

“Tá, mas como eu mantenho o sistema saudável na prática?”

Essa é a pergunta que fica no ar depois que você aceita que não vai prever tudo. E a resposta não é filosófica, é de engenharia. Existem técnicas concretas, provadas em produção e em escala, para conter o dano sem apostar tudo numa previsão perfeita.

1. Impedir que uma sobrecarga local vire uma queda total

Um paper do Facebook sobre infraestrutura serverless descreve três mecanismos que fazem exatamente isso:

Backpressure: o chamador reduz sua taxa de requisições quando o receptor sinaliza sobrecarga, e só volta a subir gradualmente. Mesmo princípio de additive-increase/multiplicative-decrease do TCP.

Limites de concorrência: um teto rígido de quantas requisições um serviço atende ao mesmo tempo, para que o excedente enfileire ou seja rejeitado em vez de degradar tudo que já está em voo.

Slow start: um serviço que acabou de se recuperar aceita tráfego gradualmente, não de uma vez. Caso contrário, a recuperação vira um segundo colapso, um thundering herd derrubando tudo de novo.

2. Projetar o desfazer, não a garantia

Assuma desde o início que uma operação de vários passos vai falhar no meio do caminho.

É o que o padrão Saga resolve. Uma transação distribuída (pedido, nota fiscal, pagamento, entrega) não precisa de uma garantia atômica impossível entre serviços separados. Ela precisa de ações compensatórias definidas de antemão para cada passo, para desfazer o que já rodou quando um passo posterior falha.

Existem duas variantes: orquestração, com um coordenador central conduzindo o fluxo (bom para processos complexos e muito dependentes entre si), e coreografia, com os serviços se comunicando por eventos e agindo de forma autônoma (bom para fluxos mais dinâmicos e desacoplados).

Nenhuma das duas tenta prever a falha. As duas assumem que ela vem e já saem com o plano B embutido no desenho.

3. Ter um kill switch

Feature flags do tipo “Ops Toggle” existem para desligar uma funcionalidade não crítica sob carga, imediatamente, sem um novo deploy. Degradar parte do sistema de propósito para manter o resto de pé.

O contraexemplo, quando esse mecanismo não existe ou existe mal gerido, é o prejuízo de US$ 460 milhões da Knight Capital: um deploy incompleto deixou código de teste antigo ativo em produção, sem uma flag confiável para desligá-lo a tempo, e a empresa queimou meio bilhão de dólares em 45 minutos.

Aquilo não foi uma falha de análise prévia. Foi a ausência de um mecanismo para conter o dano depois que a análise, inevitavelmente, deixou algo passar.

Abraçar o caos em escala industrial

Se isso soa como uma ideia bonita mas arriscada demais para uma empresa real apostar, olhe para uma indústria que já fez a aposta e tem os números para mostrar que funcionou: a aviação comercial.

Em meados dos anos 1990, as companhias aéreas americanas registravam cerca de um acidente fatal a cada dois milhões de decolagens. A resposta não foi um esforço para prever toda falha possível com mais precisão. Foi o oposto: reguladores, companhias e sindicatos de pilotos construíram um sistema de compartilhamento voluntário e não punitivo de dados de incidentes. Reportar um quase acidente deixou de significar investigação ou demissão e passou a alimentar uma base comum que a indústria inteira estudava. O resultado foi uma sequência de anos consecutivos sem um único acidente comercial doméstico fatal nos Estados Unidos, interrompida só em 2009.

Courtney Nash, no ensaio Announcing the VOID, que documenta uma tentativa de trazer essa mesma lógica para o software através de uma base pública de relatórios de incidentes de tecnologia, resume o argumento numa frase que merece a parede de todo time de infraestrutura: o potencial para resultados catastróficos é uma marca dos sistemas complexos, e esse potencial não pode ser eliminado, porque é inerente à natureza do próprio sistema.

A comunidade Learning From Incidents, citada nesse mesmo ensaio, reforça um ponto que acerta em cheio o “não fique paranoico em sempre resolver a causa”: incidentes são produtos de sistemas sociotécnicos, código, máquinas e as pessoas operando tudo isso sob pressão organizacional real, não falhas técnicas com uma única causa raiz limpa esperando para ser encontrada.

Caçar obsessivamente “a causa”, como se ela fosse sempre singular e sempre localizável, vem do mesmo instinto que faz você tentar prever toda falha antes que aconteça. Mesma origem. Mesmo teto.

O estrago real costuma ser banal

Uma última coisa para desmontar, porque a imaginação adora complicar isso. Quando você imagina “aquele cenário não identificado”, provavelmente pensa em algo sofisticado: um ataque elaborado, uma race condition rara, um bug de concorrência que só aparece em noite de lua cheia. Na prática, raramente é isso.

O vazamento da Capital One, que expôs dados de mais de 100 milhões de clientes, não foi hacking de alto nível. Foi um firewall de aplicação mal configurado que permitiu a um atacante pegar credenciais de dentro da própria infraestrutura e usá-las para ler buckets S3 que ninguém imaginava serem alcançáveis.

Nenhuma análise “completa” de superfície de ataque necessariamente teria pego aquilo. Não porque o problema fosse complexo demais para prever, mas porque era simples demais para chamar atenção. É o tipo de detalhe operacional banal que escapa justamente por parecer irrelevante demais para merecer uma linha na sua revisão de risco.

Isso não é motivo para desistir de configurar as coisas direito. É motivo para admitir que sua lista de “coisas que podem dar errado” sempre vai carregar um viés: você presta mais atenção no exótico do que no chato.

E o Cisne Negro raramente é exótico. Ele costuma ser chato.

Abraçar o caos significa…

Abraçar o caos significa aceitar a incerteza das coisas e seguir em frente. Significa trocar a energia gasta tentando fechar aquela última brecha impossível pela energia de construir os mecanismos que seguram o sistema quando a brecha, inevitavelmente, se abrir.

Significa escrever testes, sim, e também escrever planos de rollback. Definir o SLA, sim, e também definir o kill switch. Investigar o incidente, sim, mas sem a fantasia de que existe uma causa raiz única que, uma vez encontrada, te poupa da próxima.

Isso não é o oposto de disciplina. É a versão da disciplina que aceitou o próprio limite, e que gasta a energia que sobra construindo o que acontece depois desse limite em vez de fingir que o limite não está lá.

As coisas vão quebrar. A pergunta que resta é se, quando quebrarem, seu sistema vira manchete ou só mais um dia de trabalho.

Referências

  • O Cisne Negro, Nassim Nicholas Taleb: a definição de Cisne Negro, a falácia narrativa e o problema do peru
  • Antifrágil, Nassim Nicholas Taleb: frágil, robusto e antifrágil
  • Leslie Lamport (1987): a definição clássica de sistema distribuído, retomada por Roberto Vitillo em Understanding Distributed Systems
  • Designing Data-Intensive Applications, Martin Kleppmann: fault vs. failure e chaos engineering
  • Cascading failure prevention, paper de infraestrutura serverless do Facebook: backpressure, limites de concorrência e slow start
  • Padrão Saga, Saurabh Dashora: orquestração vs. coreografia
  • Feature Toggles (aka Feature Flags), Pete Hodgson / Martin Fowler: Ops Toggles e o caso Knight Capital
  • Announcing the VOID, Courtney Nash: a analogia com a aviação e a comunidade Learning From Incidents