23 pontos por GN⁺ 2025-11-19 | 8 comentários | Compartilhar no WhatsApp
  • Em 18 de novembro de 2025, às 11h20 (UTC), a função central de entrega de tráfego da rede da Cloudflare foi interrompida, fazendo com que usuários do mundo todo vissem páginas de erro
  • A causa foi o crescimento anormal do arquivo de feature do sistema de Bot Management devido a uma mudança de permissões no banco de dados, sem relação com ataque cibernético
  • Esse aumento no tamanho do arquivo fez com que o software de roteamento de tráfego excedesse seu limite e falhasse, gerando erros HTTP 5xx em larga escala
  • Por volta de 14h30, a distribuição do arquivo problemático foi interrompida e ele foi substituído pela versão anterior estável, restaurando a entrega central de tráfego; todos os serviços foram normalizados às 17h06
  • A Cloudflare avaliou o caso como a pior indisponibilidade desde 2019 e está avançando com medidas para evitar recorrência, como validação reforçada de arquivos de configuração e adoção de um kill switch global

Visão geral da indisponibilidade

  • Por volta de 11h20, ocorreu uma falha na entrega central de tráfego na rede da Cloudflare, e os usuários passaram a ver páginas internas de erro da Cloudflare
  • A causa não foi ataque cibernético nem ação maliciosa; o gatilho direto foi uma mudança de permissões no sistema de banco de dados
  • Com essa mudança, o tamanho do arquivo de feature usado pelo sistema de Bot Management dobrou e foi distribuído por toda a rede
  • Durante a leitura desse arquivo pelo software de roteamento de tráfego, o limite de tamanho do arquivo foi excedido, provocando erro no sistema
  • No início, o problema foi confundido com um grande ataque DDoS, mas, após a identificação da causa, a recuperação avançou com a substituição pelo arquivo estável anterior

Evolução e impacto da indisponibilidade

  • Antes das 11h20, a taxa de erros 5xx estava em nível normal, mas depois disso houve disparo nos erros devido à distribuição do arquivo de feature incorreto
  • Em alguns nós do cluster de banco de dados ClickHouse, resultados incorretos de consulta passaram a ser gerados a cada 5 minutos, e arquivos normais e anormais eram distribuídos alternadamente, fazendo o sistema repetir ciclos de recuperação e falha
  • A partir de 14h30, a geração do arquivo problemático foi interrompida e um arquivo correto foi inserido manualmente, com recuperação após reinicialização do proxy principal
  • Às 17h06, todos os serviços voltaram ao normal
Serviço Impacto
Core CDN e serviços de segurança Ocorrência de erros HTTP 5xx
Turnstile Falha no carregamento, impossibilidade de login
Workers KV Forte aumento de erros 5xx por falha de gateway
Dashboard Impossibilidade de login devido à falha do Turnstile
Email Security Queda temporária na precisão da detecção de spam, falha em parte das movimentações automáticas
Access Muitas falhas de autenticação, com sessões existentes mantidas
  • Durante a indisponibilidade, houve aumento na latência de resposta do CDN, causado pelo pico no uso de CPU do sistema de depuração

Causa da indisponibilidade: sistema de Bot Management

  • O módulo de Bot Management da Cloudflare usa modelos de machine learning para gerar uma pontuação de bot para cada requisição
  • O arquivo de configuração de feature usado como entrada do modelo é distribuído para toda a rede a cada poucos minutos para responder às ameaças mais recentes
  • Devido a uma mudança no comportamento de consultas do ClickHouse, muitas linhas de feature duplicadas foram incluídas, aumentando o tamanho do arquivo
  • Isso fez com que o módulo de Bot Management falhasse e retornasse respostas HTTP 5xx, afetando também Workers KV e Access
  • No novo mecanismo de proxy FL2, ocorreram erros 5xx; na versão antiga FL, a pontuação de bot foi definida como 0, aumentando falsos positivos

Mudança no comportamento de consultas do ClickHouse

  • Às 11h05, foi implantada uma mudança nas permissões de acesso ao banco de dados do ClickHouse
  • Antes, era possível consultar apenas os metadados do banco default, mas, após a mudança, os metadados do banco r0 também passaram a ficar expostos
  • A consulta de geração do arquivo de feature do Bot Management foi executada sem filtro por nome do banco de dados, resultando no retorno de colunas duplicadas
  • Com isso, o número de linhas no arquivo de feature mais que dobrou, ultrapassando o limite do sistema

Pré-alocação de memória e panic do sistema

  • O módulo de Bot Management faz pré-alocação de memória com limite máximo de 200 features de machine learning
  • Como o arquivo incorreto passou a incluir mais de 200 features, ocorreu um panic no código Rust, com a mensagem
    thread fl2_worker_thread panicked: called Result::unwrap() on an Err value
  • Isso levou à ocorrência em massa de erros HTTP 5xx

Outros impactos e processo de recuperação

  • Workers KV e Access dependiam do proxy principal, ampliando o impacto da indisponibilidade
    • Às 13h04, foi aplicado um patch para que o Workers KV contornasse o proxy, reduzindo a taxa de erros
  • O Dashboard ficou inacessível para login devido à dependência de Turnstile e Workers KV
    • Houve duas quedas de disponibilidade: 11h30–13h10 e 14h40–15h30
    • O backlog e as requisições de retry aumentaram a latência, com recuperação por volta de 15h30
  • Após 14h30, a maior parte dos serviços voltou ao normal; a recuperação completa ocorreu às 17h06

Medidas para evitar recorrência

  • Reforço da validação de entrada de arquivos de configuração gerados pela Cloudflare
  • Ampliação do kill switch global de funcionalidades
  • Prevenção de esgotamento de recursos do sistema causado por relatórios de erro
  • Revisão das condições de erro em todo o módulo de proxy principal

Resumo da linha do tempo (UTC)

Horário Estado Descrição
11h05 Normal Implantação da mudança de controle de acesso ao banco de dados
11h28 Início do impacto Primeiro erro observado no tráfego de clientes
11h32–13h05 Investigação em andamento Análise da causa dos erros no Workers KV e tentativas de mitigação
13h05 Impacto reduzido Aplicação de bypass para Workers KV e Access
13h37 Foco na recuperação Preparação do rollback do arquivo de configuração do Bot Management
14h24 Distribuição do arquivo problemático interrompida Teste do arquivo correto concluído
14h30 Principal impacto resolvido Distribuição global do arquivo correto e início da recuperação dos serviços
17h06 Recuperação completa Normalização concluída de todos os serviços

Conclusão

  • Esta indisponibilidade ocorreu pela interação entre a lógica de geração do arquivo de configuração do Bot Management e uma mudança nas permissões do banco de dados
  • A Cloudflare a classificou como a interrupção de rede mais grave desde 2019
  • A empresa pretende avançar com melhorias estruturais para reforçar a resiliência do sistema e fortalecer mecanismos automatizados de defesa

8 comentários

 
t7vonn 2025-11-19

Problemas relacionados a arquivos de configuração acontecem em qualquer lugar.

 
princox 2025-11-19

Quando a Cloudflare saiu do ar e todo tipo de serviço parou, foi um inferno mesmo..

 
epdlemflaj 2025-11-19

O documento de análise da causa foi publicado bem rápido, né?

 
epdlemflaj 2025-11-19

Aliás, o autor deste texto era o CEO.

 
GN⁺ 2025-11-19
Opiniões no Hacker News
  • Isso é uma história de incidente de .unwrap() de vários milhões de dólares
    Chamar .unwrap() em um caminho central da infraestrutura da internet equivale a declarar: “isso nunca vai falhar; se falhar, mata a thread imediatamente”
    O compilador de Rust força a possibilidade de falha a ser expressa explicitamente, mas eles escolheram o pânico em vez de tratar isso com elegância
    Parece um caso clássico do antipadrão “parse, don’t validate”

    • Muita gente parece ter um ponto cego com .unwrap(). Talvez porque ele apareça com frequência em código de exemplo
      Em código de produção real, .unwrap() e .expect() deveriam ser revisados como se fossem panic
      Se você usa .unwrap() em código de produção, deveria ser obrigatório adicionar um comentário de “INFALLIBILITY”, e isso pode ser imposto com clippy::unwrap_used
    • O ponto principal do texto parece ser que o problema foi causado não por uma única causa, mas por uma combinação de componentes normais
      Não foi apenas por causa do .unwrap(), mas porque a consulta não distinguia o banco de dados, o que aumentou o payload, e porque o ClickHouse expôs mais bancos de dados
      Em vez de concluir simplesmente que “foi por causa do unwrap”, acho mais importante melhorar o design para que um kill switch global ou algo semelhante não sobrecarregue os recursos do sistema
    • Na verdade, isso também falhou fora do caminho em Rust. O sistema de gerenciamento de bots classificou todo o tráfego como bot
      A camada FL2 deveria capturar o pânico de cada componente, mas fail-open nem sempre é melhor
      É preciso adicionar lógica para decidir explicitamente, no nível do FL2, se um pânico deve ser capturado e tratado
    • Se tivessem tratado isso com elegância, provavelmente teria havido degradação de desempenho (ainda assim, acho melhor do que perda de confiabilidade)
      Em um sistema com sharding, também fico curioso por que não houve rollout gradual e monitoramento
    • Swift tem unwrap implícito com ! e unwrap explícito com ?
      Eu quase nunca uso unwrap implícito. Mesmo quando o valor é garantido, sempre trato explicitamente
      Por exemplo, defino @IBOutlet weak var someView? em vez de @IBOutlet weak var someView!
      É uma abordagem meio belt & suspenders
  • É realmente impressionante terem publicado o post mortem menos de 24 horas após a falha

    • Fico curioso sobre a política interna que permite divulgar algo com tanta rapidez e transparência
      Na maioria das grandes empresas, seria quase impossível publicar o código por causa da revisão de vários stakeholders
    • Além disso, o texto em si foi muito bem escrito. Comparado aos post-mortems da AWS, isso chega a parecer literatura
  • Ao ler a explicação da Cloudflare sobre a falha, fiquei me perguntando: “por que a recuperação demorou tanto?”
    Entendi a causa da falha, mas se a maior parte da rede caiu, parece que reverter a alteração de configuração mais recente deveria ser a prioridade número 1
    Claro, isso fica óbvio olhando depois, mas foi impressionante terem começado a investigação em apenas 7 minutos

    • No começo, confundiram com um ataque. Depois entenderam o problema, mas não havia como substituir o arquivo corrompido na fila, e foi preciso reiniciar inúmeras máquinas no mundo todo
  • Esse caso parece parecido com o incidente da CrowdStrike
    Um arquivo de configuração gerado automaticamente quebrou o software e se espalhou pela rede inteira
    Entendo a necessidade de fazer deploy rápido, mas isso mostrou a ausência de rollout gradual e estratégia de rollback

    • É mais correto ver isso não como um deploy de CI/CD, mas como o canal de controle de um sistema distribuído de detecção de bots
    • É surpreendente que tenham enviado isso direto para produção sem um simulador
    • Ainda assim, acredito que isso vai levar a melhorias
  • Olhando para o plano de melhorias futuras anunciado pela Cloudflare, há itens como

    • fortalecer a validação de arquivos de configuração gerados pela Cloudflare
    • adicionar um kill switch global
    • evitar exaustão de recursos causada por core dumps ou relatórios de erro
    • revisar os modos de erro do módulo de proxy
      mas deploy canário ou rollout gradual de configuração não aparece
      Um switch global pode ser perigoso e, com um único bug, pode parar o sistema inteiro
    • As configurações de gerenciamento de bots precisam se propagar rápido, mas se tivessem testado primeiro em uma instância, teriam capturado o pânico antes
      Também fico em dúvida sobre por que usaram o ClickHouse como repositório de feature flags. A documentação de deduplicação do ClickHouse também menciona riscos
    • O serviço de configuração tinha rollout gradual, mas os serviços consumidores se atualizavam automaticamente com frequência demais, então até uma pequena taxa de erro afetou tudo
    • Configurações globais são úteis para resposta rápida, mas um mecanismo de rollback rápido é indispensável
      Se houvesse um mapeamento de dependências entre serviços, seria muito mais fácil rastrear a causa
    • No fim, a maioria das grandes falhas acontece por causa de config push
      Deploy de código é tratado com cuidado, mas deploy de configuração não. É preciso encarar configuração como código
  • Achei interessante a parte em que a página de status caiu e isso levou a acharem que era um ataque
    Dizem que ela é totalmente separada da infraestrutura da Cloudflare, mas não há explicação de por que caiu junto

    • Provavelmente foi uma falha de escalabilidade da infraestrutura causada por pico de tráfego
    • Na prática, talvez pensassem que não havia dependência da Cloudflare, mas como uma parte considerável da internet depende do CloudFront, talvez não fosse totalmente independente
    • Para saber a causa, seria preciso um post mortem do statuspage.io. É um serviço operado pela Atlassian
    • Também pode ser simplesmente que o volume de tráfego gerado pela escala da Cloudflare tenha sido grande demais
  • Eu integrei o Turnstile com uma estratégia fail-open, e isso ajudou nesta falha
    Se o JS não carrega, permito o envio com um token fictício e, mesmo quando a validação falha no backend, trato como fail-open
    Alguns usuários ainda foram bloqueados, mas o impacto geral foi reduzido
    É uma abordagem possível porque existem outros mecanismos de mitigação de bots

    • Nesse caso, surge a dúvida: se um atacante bloquear o script, não conseguiria contornar o CAPTCHA?
      Mas isso parece funcionar apenas quando não se trata de um ataque direcionado
  • Fico me perguntando por que permitiram .unwrap() no código da Cloudflare
    No mínimo, deveriam ter usado expect("isso nunca deveria acontecer")
    A filosofia de tratar erros como valores existe justamente para evitar esse tipo de problema, e também teria tornado o diagnóstico muito mais fácil

    • Eu não trabalho na Cloudflare, mas uso bastante Rust
      Em código que inclui chamadas de rede, há possibilidades demais de falha
      Durante o desenvolvimento eu uso .unwrap(), mas em produção às vezes deixo expect() mesmo assim, porque há casos em que simplesmente não existe como continuar
  • A verdadeira lição é que funções demais dependem de poucos players
    A dinâmica de vencedores levam tudo está se aprofundando, e a resiliência do sistema está diminuindo
    Claro que eles conquistaram essa posição por mérito, mas parece exagerado esperar que a internet esteja sempre “funcionando normalmente”

  • A ideia de que “com Rust tudo é seguro” é exagerada
    Em qualquer linguagem, se você usar errado, é como apontar a arma para o próprio pé

 
barca105 2025-11-19

Até uma empresa do porte da CF usa .unwrap(), caramba. Como é que esse código foi parar em produção?

 
skageektp 2025-11-19

Não parece que o problema seja o unwrap.

 
barca105 2025-11-19

O problema fundamental é a consulta incorreta.
Mas também acho que foi um problema terem pulado a validação do problema com unwrap.
Mesmo que surgisse um problema internamente, se tivessem tratado o erro, o tráfego não teria caído.