Tipo de Demo · 12

Relatório de Incidente (RCA)

Use isto quando quiser ensinar uma lição difícil por meio de uma falha real — uma linha do tempo do que aconteceu, a causa raiz desenterrada com os 5 porquês, o raio de impacto e as correções com responsáveis.

Este é um exemplar copiável. Leve a seção de demo abaixo para uma lição construída a partir de assets/lesson-template.html — mantenha os tokens de design e o padrão Simples → Técnico intactos.

1

O que aconteceu, em palavras simples


Na manhã de 14 de março, nosso app principal parou de salvar qualquer coisa. As pessoas conseguiam abri-lo e clicar por aí, mas toda tentativa de gravar dados falhava. O motivo acabou sendo constrangedoramente simples: o disco do servidor de banco de dados estava completamente cheio. Sem espaço para gravar, o banco de dados recusou todos os novos registros.

Um relatório como este percorre a falha com honestidade para que a mesma coisa nunca nos pegue duas vezes. Ele tem quatro partes que você pode ler de cima a baixo: uma linha do tempo dos eventos, a causa raiz encontrada perguntando "por quê?" cinco vezes, um resumo de impacto e uma checklist de correções com um responsável nomeado para cada uma.

Pense nisso como… uma pia de cozinha que transborda porque o ralo vinha entupindo lentamente havia semanas. A inundação é o incidente; a história real é o entupimento que ninguém estava observando — e a correção é um alarme de ralo, não apenas um esfregão.

O que de fato falhou

A instância primária do Postgres (db-prod-01) atingiu 100% de uso em seu volume de dados. O Postgres entrou em estado somente leitura quando o diretório do write-ahead log (WAL) não conseguiu mais fazer o flush, manifestando-se como PANIC: could not write to file "pg_wal/…": No space left on device. A camada de aplicação traduziu isso em HTTP 500 em todo endpoint de escrita, enquanto as leituras do cache continuavam, e foi por isso que o app "parecia" vivo.

Por que o disco encheu silenciosamente

Três fatores se acumularam: (1) um nível de log debug verboso enviado para produção duas semanas antes inflou o volume de WAL e de logs; (2) o VACUUM automático estava desabilitado em uma tabela grande do tipo append-only, então as tuplas mortas nunca liberavam espaço; (3) o único alerta de disco era um painel manual que ninguém tinha aberto às 03:00. Não existia nenhum alarme de limiar abaixo de 100%.

2

O incidente em resumo


SEV-1

O dia em que o disco do banco de dados encheu

Detectado2026-03-14 · 03:12 UTC
Resolvido2026-03-14 · 04:47 UTC
Duração1h 35min
Serviçodb-prod-01 (escritas)
AutorPlantão · Plataforma
3

Linha do tempo dos eventos


Leia de cima a baixo. Os pontos verde-oliva são rotina, os de cor argila são um sinal de alerta, o vermelho é a falha e o verde é a recuperação. Note como o problema começou semanas antes de alguém perceber.

  1. 28 fev

    Log em debug enviado para produção

    Um deploy mudou o nível de log do banco para debug "temporariamente" para uma investigação. Nunca foi revertido.

    raiz em movimento
  2. 11 mar

    Disco ultrapassa 85%

    O volume de dados passa silenciosamente de 85% de uso. Nenhum alerta está configurado nesse limiar, então ninguém é acionado.

    sinal perdido
  3. 03:09

    Disco chega a 100% — escritas falham

    O Postgres não consegue mais fazer o flush do write-ahead log e cai em somente leitura. Todo salvamento no app começa a retornar erros.

    início do incidente
  4. 03:12

    Primeiro relato de cliente

    Um usuário envia e-mail ao suporte: "Não consigo salvar meu trabalho." O plantão é acionado 3 minutos depois pelo alarme de taxa de erros, não pelo disco.

    detectado
  5. 03:31

    Causa raiz identificada

    O plantão executa df -h no host e vê 100% /var/lib/postgresql. A causa agora está clara.

    diagnosticado
  6. 03:58

    Espaço recuperado em emergência

    WAL antigo e logs rotacionados são arquivados fora da máquina e o volume cresce em 40 GB. As escritas voltam em minutos.

    mitigado
  7. 04:47

    Serviço confirmado saudável

    Taxa de erros de volta ao patamar normal, latência de escrita normal, nenhum dado perdido. Incidente encerrado; postmortem agendado.

    resolvido
28 fev log debug enviado 11 mar disco 85% (sem alerta) 03:09 100% — escritas falham 03:12 detectado 03:58 mitigado 04:47 resolvido
A mesma história comprimida: a causa raiz (log debug) foi acesa duas semanas antes da queda.
4

Causa raiz — cinco porquês


Continue perguntando "mas por que isso aconteceu?" até chegar a algo que você possa de fato corrigir. A primeira resposta ("o disco estava cheio") é um sintoma, não uma causa. A quinta resposta é a que vale a pena corrigir.

  1. Por que o app parou de salvar?

    O banco de dados recusou todas as escritas.

  2. Por que o banco de dados recusou as escritas?

    Seu disco estava 100% cheio — o Postgres não conseguia mais fazer o flush do write-ahead log.

  3. Por que o disco encheu?

    O volume de logs e de WAL vinha crescendo de forma incomumente rápida, e as linhas mortas em uma tabela grande nunca foram liberadas.

  4. Por que o crescimento passou despercebido?

    Não havia alerta abaixo de 100%. O uso de disco vivia em um painel que ninguém observa às 3 da manhã.

  5. Causa raiz · por que não existia alerta antecipado

    A capacidade de disco nunca foi tratada como um SLO de primeira classe. Uma mudança "temporária" no log debug foi enviada sem ticket de reversão, e ninguém era responsável por alertas proativos de capacidade. O sistema não tinha como nos avisar antes de quebrar.

Fatores contribuintes (não a raiz única)

Os 5 porquês encontram a cadeia principal; incidentes reais têm desvios. Aqui: o autovacuum foi desabilitado em events_raw durante uma migração passada e nunca foi reativado; a janela de retenção de WAL estava alta por causa de uma réplica desde então removida; e o runbook de "disco cheio" estava três anos desatualizado. Nenhum sozinho causou a queda, mas cada um encurtou o pavio.

Por que evitamos culpar

O engenheiro que enviou o log debug agiu de forma razoável dadas as ferramentas — não havia guarda-corpo, lembrete de reversão nem alarme de capacidade. Um postmortem sem culpados corrige o sistema (adicionar o alarme, adicionar tickets de reversão) em vez da pessoa.

5

Resumo de impacto


O raio de impacto em números — o que custou e a boa notícia no final.

1h 35min

Indisponibilidade de escrita

~4.200

Tentativas de salvar falhas

~310

Usuários afetados

0

Registros perdidos
6

Itens de ação


Cada correção tem um responsável e uma prioridade. Marque os itens conforme forem entregues — a barra acompanha o progresso. P1 fecha a porta exatamente para esta falha; P2/P3 reforçam a área ao redor dela.

0 de 5 concluídos
  • P1
  • P1
  • P2
  • P2
  • P3