No sábado, 4 de abril de 2026, o plano de dados do AppView do Bluesky — o backend que atende as leituras do aplicativo social — começou a registrar erros como 'failed to set post cache item: dial tcp: bind: address already in use'. O plano de dados depende fortemente do memcached para aliviar a carga do seu banco principal Scylla, e Jim Calabro, o engenheiro de infraestrutura de plantão, viu os picos de log coincidirem com quedas no tráfego voltado ao usuário. O monitoramento de rede estava limpo, então a causa permaneceu oculta durante o fim de semana enquanto o serviço seguia mancando.

A causa raiz era um novo serviço interno implantado naquela semana: menos de três requisições GetPostRecord por segundo, mas 15.000–20.000 URIs de posts por lote (o normal é de 1 a 50). Todo manipulador de RPC do plano de dados limita a concorrência com errgroup.SetLimit — apenas esse endpoint estava sem essa linha. Uma única chamada gerava até 20.000 goroutines, discando uma tempestade de conexões ao memcached; quando o pool ocioso de 1.000 sockets transbordou, elas se acumularam em TCP TIME_WAIT e esgotaram todas as portas efêmeras. O cliente rodava em um único data center e, sem métricas por cliente, erros de cache de todos os tipos mascaravam o culpado.

Na segunda-feira, 6 de abril, a situação mergulhou numa espiral da morte: com milhões de requisições ao memcached falhando por segundo, a política do Bluesky de registrar todo erro tentava milhões de gravações de log write(2) bloqueantes por segundo. A enxurrada de chamadas de sistema bloqueantes levou o runtime Go de cerca de 150 para 1.500 threads de SO, privando o GC de recursos e provocando longas pausas stop-the-world. O ajuste agressivo de GOGC e GOMEMLIMIT fez o plano de dados sofrer falhas periódicas por OOM — no ar por cerca de 30 minutos, caía, repetia. Cada reinício aprofundava o buraco: sockets em TIME_WAIT deixavam o processo reiniciado incapaz de recriar seu pool de memcached.

O curativo de segunda-feira foi gloriosamente absurdo: um dialer personalizado que escolhia um IP de loopback 127.x.y.z aleatório para cada conexão de saída, ampliando o espaço de ip+porta além da faixa esgotada. Isso deteve a espiral, e só na quarta-feira a equipe encontrou a verdadeira causa raiz e restaurou o SetLimit(50) ausente. O post-mortem público de Calabro também assumiu uma falha de comunicação: a página de status havia culpado um provedor de rede terceirizado, o que 'claramente não era o caso'.

Indisponibilidade intermitente para aproximadamente metade de todos os usuários do Bluesky ao longo de cerca de oito horas em 6 de abril de 2026 — a pior queda da plataforma no tempo de seu líder de infraestrutura ali

A concorrência limitada era imposta por convenção, não por estrutura: todo manipulador tinha SetLimit exceto um, e um único endpoint sem limite bastou para esgotar recursos no nível do host.

O contrato de tráfego não tinha limites de forma: nada rejeitava um lote de 20.000 itens, então um cliente interno discreto — 3 requisições por segundo — superou milhões de clientes normais como fonte de carga.

O tratamento de falhas amplificou a falha: registrar todo erro de memcached a milhões de erros por segundo converteu um problema de cache em explosão de threads, pausas de GC e falhas por OOM.

A observabilidade pressupunha requisições pequenas e não tinha métricas por cliente, então erros de todos os tipos de cache esconderam o único chamador e o único endpoint responsáveis por dias.

O reinício como recuperação estava quebrado: sockets em TIME_WAIT do processo morto impediam o novo processo de reconstruir seus pools de memcached, transformando reinícios por OOM em mais esgotamento de portas.

Um único laço de goroutines sem limite superou todas as outras salvaguardas. Limites de concorrência devem ser estruturais, não um hábito por endpoint: o único endpoint sem um tornou-se o incidente inteiro.

O serviço foi estabilizado na segunda-feira com o dialer de loopback aleatório, que foi removido assim que a correção real — a restauração do limite de concorrência — entrou no ar na quarta-feira, 8 de abril. A exposição total foi de cerca de oito horas de indisponibilidade intermitente para aproximadamente metade dos usuários. O post-mortem, publicado em 10 de abril de 2026, prometeu observabilidade por cliente, detecção de clientes que enviam pequenos números de requisições superdimensionadas e uma mudança do registro de logs em alto volume para métricas Prometheus e rastreamento OpenTelemetry; ele rendeu uma análise independente detalhada do pesquisador de confiabilidade Lorin Hochstein dois dias depois.

CONFIRA AS EVIDÊNCIAS

As fontes

  1. April 2026 Outage Post-Mortem Jim Calabro (Bluesky infrastructure engineer), pckt.blog · pckt.blog ·
  2. Thoughts on the Bluesky public incident write-up Surfing Complexity (Lorin Hochstein) · surfingcomplexity.blog ·
  3. Bluesky April 2026 Outage Post-Mortem (discussion, 141 points) Hacker News · news.ycombinator.com ·