Pular para o conteúdo
fernando.moretes.com
BlogEstudosCursosE-booksOpen SourcePodcasts
Loading…
Fernando Azevedo

Arquiteto de TI Especialista

Arquitetura, AWS, IA em produção, sistemas financeiros e FinOps, escritos a partir do que foi operado, com os números.

  • LinkedIn
  • GitHub
  • E-mail

Conteúdo

  • Blog
  • Estudos de arquitetura
  • Cursos
  • E-books
  • Open Source
  • Podcasts
  • Assuntos
  • Trilhas

Ferramentas

  • Well-Architected self-check
  • Arquitetura deste site
  • Números públicos
  • Histórico de estudo

Sobre

  • Comunidade
  • IA Builder
  • Perfil
  • Currículo (CV)
  • Trabalhe comigo
  • Media kit
  • RSS do blog
  • RSS dos estudos
  • Artigos narrados (podcast)
  • llms.txt
  • Termos, privacidade e uso de IA

(c) 2026 Fernando Francisco Azevedo

Estudos/Post-mortem
RSSMarkdownLLMs
Post-mortemAWSResiliência

AWS Kinesis us-east-1 (2020): Quando um Limite de Threads do SO Derrubou Metade da AWS

25 de nov. de 2020 10 min Com apoio de IA000 visualizações00 reproduções

Em novembro de 2020, uma expansão de capacidade no front-end do Amazon Kinesis esgotou o limite de threads por processo do sistema operacional, causando falhas em cascata que afetaram Cognito, CloudWatch, Lambda, ECS e dezenas de outros serviços na região us-east-1 por mais de oito horas. O incidente expôs dependências ocultas entre serviços AWS e os riscos de mudanças operacionais aparentemente seguras em sistemas de larga escala.

Ouvir estudo

cerca de 10 min · áudio gerado ao tocar

Ficha do Incidente

Empresa / Sistema
Amazon Web Services: Amazon Kinesis Data Streams
Data do Incidente
25 de novembro de 2020
Duração Total
Aproximadamente 8 horas (início ~07:45 UTC; recuperação parcial ao longo do dia)
Região Afetada
us-east-1 (Norte da Virgínia), a maior região AWS
Serviço Origem
Amazon Kinesis Data Streams (servidores front-end)
Serviços Impactados
Cognito, CloudWatch, Lambda, ECS, CloudFormation, EventBridge, Auto Scaling, Console AWS, e mais de 20 outros serviços
Causa Raiz
Esgotamento do limite de threads por processo do SO nos servidores front-end do Kinesis após adição de capacidade
Stack Técnico
Servidores front-end Java/JVM, shards Kinesis, dependências internas via SDK AWS (que usa Kinesis internamente)
Impacto nos Clientes
Falhas de autenticação (Cognito), ausência de métricas e alarmes (CloudWatch), falhas de deploy e scaling, em plena Black Friday

Um único limite de configuração do sistema operacional, o número máximo de threads por processo, transformou uma rotina de expansão de capacidade em um dos incidentes mais amplos da história pública da AWS. O que parecia ser um ajuste operacional seguro revelou uma rede de dependências internas que ninguém havia mapeado completamente, e derrubou serviços que, na superfície, não tinham nada a ver com streaming de dados.

O Que Aconteceu

Na manhã de 25 de novembro de 2020, véspera do Thanksgiving nos EUA e início da semana da Black Friday, a equipe do Amazon Kinesis executou uma expansão de capacidade planejada na região us-east-1. O objetivo era aumentar o número de servidores front-end do Kinesis para suportar a carga crescente esperada para o período de pico comercial. Trata-se de uma operação de rotina em qualquer sistema distribuído de larga escala: adicionar nós para distribuir carga.

O problema estava em um detalhe de implementação dos servidores front-end do Kinesis. Cada servidor front-end mantém conexões com todos os outros nós do cluster, um modelo de topologia all-to-all que é comum em sistemas que precisam rotear requisições para shards específicos sem uma camada adicional de indireção. À medida que o número de servidores front-end aumentava, cada servidor precisava abrir e manter mais conexões simultâneas. Cada conexão, por sua vez, utilizava uma thread dedicada para gerenciamento I/O.

O sistema operacional Linux impõe um limite no número de threads que um único processo pode criar, o parâmetro ulimit -u (ou threads-max em nível de kernel). Quando o número de servidores front-end cruzou um determinado limiar, os processos Java nos servidores existentes tentaram criar novas threads para gerenciar as conexões com os novos nós e falharam com erros do tipo java.lang.OutOfMemoryError: unable to create new native thread. A partir desse ponto, os servidores front-end do Kinesis começaram a rejeitar requisições e a apresentar falhas de health check.

Até aqui, o incidente seria contido ao Kinesis. O que transformou isso em um desastre regional foi algo que a maioria dos engenheiros externos à AWS não sabia: uma parcela significativa dos serviços AWS internos utiliza o próprio Kinesis como infraestrutura de telemetria, logging e entrega de eventos. O SDK interno da AWS, utilizado por serviços como Cognito, CloudWatch, Lambda e ECS para publicar métricas e logs, dependia do Kinesis. Quando o Kinesis ficou degradado, esses serviços começaram a acumular filas de envio de telemetria, e os próprios mecanismos de health check e recuperação automática desses serviços, que dependiam de CloudWatch para alarmes e de Cognito para autenticação de chamadas internas, também falharam.

Linha do Tempo do Incidente

  1. 1

    ~07:30 UTC: Expansão de Capacidade Iniciada

    A equipe do Kinesis inicia a adição de servidores front-end na região us-east-1 como parte de um procedimento planejado de scaling para a semana da Black Friday.

  2. 2

    ~07:45 UTC: Primeiras Falhas no Kinesis

    Servidores front-end existentes começam a falhar ao tentar criar novas threads para gerenciar conexões com os nós recém-adicionados. Erros de OutOfMemoryError: unable to create new native thread surgem nos logs. Health checks começam a falhar.

  3. 3

    ~08:00 UTC: Degradação se Propaga para Cognito e CloudWatch

    Serviços que dependem do Kinesis internamente para telemetria começam a apresentar erros. Cognito passa a falhar em autenticações. CloudWatch deixa de receber métricas e alarmes param de disparar, incluindo os alarmes que deveriam alertar as equipes sobre o próprio incidente.

  4. 4

    ~08:30 UTC: Lambda, ECS e Outros Serviços Afetados

    O efeito cascata se amplia. Lambda apresenta falhas de invocação. ECS falha em operações de gerenciamento de tarefas. CloudFormation e EventBridge são impactados. O Console AWS fica parcialmente indisponível, dificultando o diagnóstico manual.

  5. 5

    ~09:00 UTC: Diagnóstico da Causa Raiz

    As equipes da AWS identificam o esgotamento de threads como causa raiz. A decisão é reverter a expansão de capacidade e reduzir o número de servidores front-end para abaixo do limiar crítico.

  6. 6

    ~10:00–14:00 UTC: Recuperação Gradual

    O rollback do Kinesis começa a surtir efeito. Serviços dependentes se recuperam à medida que o Kinesis volta a aceitar conexões. A recuperação é não-uniforme: alguns serviços se recuperam rapidamente, outros levam horas devido a filas acumuladas e estados inconsistentes.

  7. 7

    ~18:00 UTC: Recuperação Substancial

    A maioria dos serviços afetados retorna à operação normal. A AWS publica comunicados no Service Health Dashboard ao longo do dia, embora com atraso em relação à severidade real do incidente.

Fluxo de Falha: Do Limite de Threads ao Colapso em Cascata

O diagrama reconstrói como o esgotamento de threads nos servidores front-end do Kinesis se propagou para serviços aparentemente não relacionados através de dependências internas de telemetria e autenticação.

🔧 Operação de Scaling (Gatilho)
  • Capacity Expansion · Novos front-ends adicionados
📡 Kinesis Front-End Layer
  • Front-End Servers · (existentes) · All-to-all mesh
  • Front-End Servers · (novos) · Adicionados no scaling
  • OS Thread Limit · ulimit -u esgotado · OOME: native thread
🗄️ Kinesis Data Plane
  • Kinesis Shards · Backend storage
📊 Serviços Dependentes (Telemetria Interna)
  • CloudWatch · Métricas e alarmes · param de funcionar
  • Amazon Cognito · Autenticação falha · para usuários finais
  • AWS Lambda · Falhas de invocação · e cold start
  • Amazon ECS · Falhas de task · management
🔄 Serviços de Controle Afetados
  • CloudFormation · Deploys falham
  • EventBridge · Entrega de eventos · degradada
  • AWS Console · Parcialmente · indisponível
👤 Impacto Final
  • Clientes AWS · Autenticação, deploys, · scaling, observabilidade

Causa Raiz: O Limite que Ninguém Estava Monitorando

A causa raiz é tecnicamente simples e operacionalmente devastadora: os servidores front-end do Kinesis utilizavam uma thread por conexão de saída para gerenciar o mesh all-to-all entre nós do cluster. Quando novos servidores foram adicionados, cada servidor existente tentou abrir novas conexões, e portanto criar novas threads, até atingir o limite do sistema operacional (ulimit -u). No Linux, esse limite é por processo e, em configurações padrão de muitas distribuições, pode ser surpreendentemente baixo (tipicamente 4096 a 32768 threads por processo, dependendo da configuração). A JVM, ao falhar em criar uma nova thread nativa, lança OutOfMemoryError: unable to create new native thread, que não é um erro de heap, é um erro de recursos do SO. O servidor não estava sem memória RAM; estava sem espaço na tabela de threads do kernel. O limite não estava sendo monitorado ativamente, e não havia um circuit breaker que impedisse a adição de novos nós quando o servidor de destino estava próximo do limiar crítico.

O Efeito Cascata: Dependências que Ninguém Documentou

O aspecto mais instrutivo deste incidente não é o bug em si, é o que ele revelou sobre a arquitetura interna da AWS. O Kinesis não é apenas um serviço de streaming para clientes externos; ele é uma peça de infraestrutura interna crítica usada por outros serviços AWS para transportar telemetria, logs e eventos de controle. Essa é uma decisão arquitetural que faz sentido: usar o próprio produto como infraestrutura interna (dogfooding) valida o serviço em produção real e reduz a necessidade de manter stacks de observabilidade paralelas.

O problema é que essa dependência criou um acoplamento estrutural não documentado publicamente. Quando o Kinesis falhou, o CloudWatch, que dependia do Kinesis para ingerir métricas, parou de receber dados. Sem métricas chegando, alarmes que deveriam disparar automaticamente ficaram silenciosos. Isso criou uma situação de alarm blindness: as próprias ferramentas que deveriam detectar e alertar sobre o incidente estavam comprometidas pelo incidente. As equipes de on-call perderam visibilidade justamente quando mais precisavam dela.

O Cognito, por sua vez, usava Kinesis para telemetria interna. Quando o Kinesis ficou degradado, chamadas de autenticação do Cognito começaram a falhar, não porque o Cognito em si estava quebrado, mas porque o caminho de telemetria estava bloqueado e isso afetava o fluxo de controle. Isso impactou diretamente usuários finais que dependiam do Cognito para autenticação em suas aplicações, e também impactou o Console AWS, que usa Cognito para autenticação de sessão. O resultado foi que engenheiros tentando diagnosticar o problema pelo Console também encontravam dificuldades para fazer login.

Esse padrão, onde o sistema de observabilidade depende do sistema que está falhando, é um anti-padrão clássico de resiliência. Em sistemas financeiros onde trabalhei, chamamos isso de observer coupling: quando o observador e o observado compartilham o mesmo plano de falha, você perde a capacidade de diagnóstico exatamente quando mais precisa dela. A solução arquitetural é garantir que o plano de controle e observabilidade seja completamente independente do plano de dados que está sendo monitorado.

Remediação: O Que a AWS Fez e o Que Prometeu Mudar

A remediação imediata foi direta: reverter a expansão de capacidade, reduzindo o número de servidores front-end para abaixo do limiar que causava o esgotamento de threads. À medida que os servidores front-end voltaram a funcionar normalmente, os serviços dependentes começaram a se recuperar, primeiro o Kinesis em si, depois CloudWatch, depois Cognito, e assim por diante, em ordem inversa à cascata de falhas.

A AWS publicou um post-mortem detalhado (Summary of the Kinesis Event) que identificou várias ações corretivas. Em termos de mitigação imediata, a equipe aumentou os limites de threads do SO nos servidores front-end e modificou o código para usar conexões assíncronas (non-blocking I/O) em vez de threads dedicadas por conexão, uma mudança arquitetural que elimina a dependência linear entre número de conexões e número de threads. Com NIO/async, um único pool de threads pode gerenciar milhares de conexões simultâneas.

Para prevenir recorrência, a AWS comprometeu-se com: (1) monitoramento ativo de métricas de recursos do SO, incluindo uso de threads, em todos os serviços críticos; (2) implementação de testes de capacidade que validem limites de recursos do SO antes de mudanças operacionais de scaling; (3) revisão das dependências internas entre serviços para identificar e mitigar acoplamentos que poderiam propagar falhas; (4) melhoria do plano de observabilidade para garantir que métricas críticas de saúde dos serviços sejam entregues por um caminho independente do Kinesis quando o Kinesis está degradado.

Do ponto de vista de clientes, a lição operacional é clara: não assuma que o Service Health Dashboard da AWS reflete com precisão e em tempo real o estado de todos os serviços. Durante este incidente, o dashboard estava ele próprio comprometido pelo mesmo problema que afetava o CloudWatch. Sistemas críticos devem ter health checks sintéticos independentes, fora da AWS ou em múltiplas regiões, que validem o comportamento real da aplicação, não apenas o status reportado pelo provedor.

FA
Minha Leitura Sênior: O Que Este Incidente Realmente Ensina
Arquiteto de TI Especialista

Trabalho com sistemas distribuídos de missão crítica há mais de 16 anos, incluindo infraestrutura financeira onde falhas de oito horas simplesmente não são aceitáveis. Este incidente me interessa menos pelo bug em si, um ulimit mal configurado é um erro operacional clássico, e muito mais pelo que ele revela sobre a natureza das dependências em sistemas de larga escala. O ponto que mais me chama atenção é a observer coupling: o CloudWatch dependia do Kinesis para funcionar, e o Kinesis estava quebrado. Isso não é um bug; é uma decisão arquitetural que se tornou um ponto único de falha para o plano de observabilidade. Em qualquer sistema que projeto, o plano de observabilidade (métricas, logs, alertas) deve ser arquiteturalmente isolado do plano de dados. Se você usa o mesmo barramento para transportar dados de negócio e telemetria de sistema, uma falha no barramento te cega exatamente quando você mais precisa de visibilidade. Segundo ponto: a topologia all-to-all entre servidores front-end é uma escolha que escala O(n²) em número de conexões. Para n=10 servidores, são 90 conexões. Para n=100, são 9.900. Esse tipo de crescimento quadrático em recursos é uma bomba-relógio em qualquer sistema que precise escalar horizontalmente. A migração para NIO/async resolve o problema de threads, mas não resolve o problema de O(n²) conexões, para isso, você precisa de uma camada de roteamento intermediária (um service mesh, um proxy de shard, ou um protocolo gossip) que reduza a conectividade necessária.

Lições Aprendidas

Limites de recursos do SO são invisíveis até que explodam. ulimit -u, file descriptors, max_map_count, esses parâmetros raramente aparecem em dashboards de capacidade padrão. Monitore-os ativamente e defina alertas com margem de segurança (ex: alerta a 70% do limite máximo).
Topologias all-to-all escalam quadraticamente. Qualquer mesh onde cada nó se conecta a todos os outros tem crescimento O(n²) em conexões. Antes de escalar horizontalmente, valide que a topologia de rede suporta o número-alvo de nós sem explodir recursos.
O plano de observabilidade não pode depender do plano de dados que monitora. Se seu sistema de alertas usa a mesma infraestrutura que está monitorando, você perde visibilidade no pior momento. Separe arquiteturalmente o caminho de telemetria do caminho de dados.
Dependências internas de provedores cloud são caixas-pretas. Você não sabe quais serviços AWS dependem de quais internamente. Projete para a falha de qualquer serviço individual, incluindo Cognito, CloudWatch e Kinesis.
Thread-per-connection é um anti-padrão para servidores de alta conexão. Em 2020, NIO/async já era a abordagem padrão para servidores de alta concorrência. Sistemas que ainda usam thread-per-connection têm um teto de escala determinístico e baixo.
Congele mudanças operacionais de alto risco antes de períodos críticos de negócio. Expandir capacidade na véspera da Black Friday é um risco desnecessário. Mudanças de infraestrutura devem ser concluídas e estabilizadas com antecedência suficiente para permitir rollback seguro.

Análise pelo AWS Well-Architected Framework

Segurança

Impacto indireto: a falha do Cognito comprometeu fluxos de autenticação de usuários finais. Dependências de autenticação sem fallback tornaram-se pontos únicos de falha para acesso a sistemas críticos.

Confiabilidade

Falha crítica em múltiplas dimensões: ausência de circuit breakers para limites de recursos do SO, topologia de rede com crescimento quadrático não testada em escala, dependências circulares entre serviço e seu sistema de observabilidade, e ausência de isolamento de falhas entre o plano de dados e o plano de controle.

Sustentabilidade

Não aplicável como fator causal neste incidente.

Veredicto: Um Incidente Simples com Lições Complexas

O incidente do Kinesis de novembro de 2020 é, na superfície, uma história sobre um ulimit mal configurado. Na profundidade, é uma história sobre como sistemas de larga escala acumulam dependências ocultas que só se tornam visíveis quando falham, e sobre como a falha de um componente pode paralisar o próprio sistema de diagnóstico que deveria detectá-la. A AWS merece crédito pelo post-mortem detalhado e pela transparência sobre a causa raiz. Mas o incidente também expõe uma tensão fundamental no modelo de operação de um provedor cloud: quanto mais você usa seus próprios serviços como infraestrutura interna (dogfooding), mais você cria acoplamentos que podem amplificar falhas locais em colapsos regionais. Para engenheiros construindo sobre AWS, ou qualquer provedor cloud, a lição central é esta: você não pode assumir que o plano de controle do seu provedor é independente do plano de dados que você usa. Projete seus sistemas assumindo que qualquer serviço AWS pode falhar, incluindo os serviços de observabilidade. Implemente health checks sintéticos externos. Tenha fallbacks de autenticação.

Referências

AWS: Summary of the Amazon Kinesis Event in the Northern Virginia (US-EAST-1) Region
#postmortem#aws#kinesis#resiliência#cascata#threads#us-east-1#dependências
Fontes do caso
AWS: Summary of the Kinesis Event
Compartilhar:LinkedInWhatsAppXBaixar em Markdown
Escrito com apoio de IA a partir do caso público e da minha leitura como arquiteto.
Próximo passo
Trilha Arquiteto de IA, gratuitaFundamentos, LLMs, RAG, tools, MCP e arquitetura na AWS, em aulas curtas e interativas.Começar a trilhaAgentes de IA em produção na AWSComo eu desenho, oriento e audito agentes que vão ao ar, com os números e as fontes.Ver o IA Builder

Continue lendo

Post-mortemAWS S3 us-east-1 (2017): quando um typo derruba a internetEm 28 de fevereiro de 2017, um engenheiro da AWS executou um comando de debug com um parâmetro incorreto e removeu uma quantidade muito maior de servidores do subsistema de indexação do S3 do que o pretendido. O resultado foi quatro horas de degradação severa em us-east-1 que afetou centenas de serviços dependentes, de ferramentas de monitoramento a grandes plataformas SaaS. O incidente expôs fragilidades estruturais em torno de dependências implícitas, ausência de rate limiting em operações destrutivas e a falácia de assumir que uma única região AWS seria suficientemente resiliente.Ler Post-mortemAWS us-east-1 (2025): Evento Térmico em Datacenter Derruba EC2 e EBSUma falha no sistema de refrigeração de um datacenter em us-east-1 causou superaquecimento de servidores, acionando desligamentos de proteção térmica que degradaram EC2 e EBS na região. O incidente reacende debates críticos sobre concentração de workloads em us-east-1, o papel do isolamento físico por AZ e a necessidade de graceful degradation em arquiteturas de produção.Ler Post-mortemCloudflare (2026): quando uma dependência single-AZ derruba um cluster 'HA'Em 20 de fevereiro de 2026, a Cloudflare sofreu um outage no plano de controle e em analytics porque Kafka e ClickHouse, serviços críticos de ingestão e consulta de dados, existiam apenas na zona PDX-04, enquanto o cluster declarado como de alta disponibilidade dependia deles de forma implícita. O incidente expõe um padrão recorrente em sistemas distribuídos: a ilusão de HA criada por redundância parcial que não cobre todas as dependências da cadeia.Ler
AnteriorUber DOMA: Como Camadas de Domínio Domaram a Explosão de MicrosserviçosPróximoNetflix: Chaos Engineering e Resiliência por Design
Gostou deste estudo? Receba o próximo.

Post-mortems, ADRs e deep dives de arquitetura no seu email, do jeito que um arquiteto lê.

Sem spam · cancele quando quiser

Pergunte ao Fernando sobre isto

Uma resposta focada sobre este estudo, do meu assistente de IA, baseada no meu trabalho.

Participe da conversa

Entre para comentar

Confirme seu e-mail para participar, você também recebe a newsletter. Sem senha.

Neste estudo
O Que AconteceuLinha do Tempo do IncidenteArquiteturaO Efeito Cascata: Dependências que Ninguém DocumentouRemediação: O Que a AWS Fez e o Que Prometeu MudarWell-ArchitectedVeredicto: Um Incidente Simples com Lições ComplexasReferências