MÓDULO 10 · CONCEITO 06 DE 12

Alertas e On-call

Threshold vs SLO-based alerting, burn rate alerts, Alertmanager, alert fatigue e a cultura de on-call sustentável

Tempo de leitura ~32 min Pré-requisito 05 · OpenTelemetry Próximo 07 · Dashboards e Grafana

Alertar bem é mais difícil do que parece. A tentação é simples: adicionar um alerta para cada métrica que pode dar errado. O resultado é uma coleção de thresholds arbitrários que disparam às 3am, ninguém acorda com urgência real, e o time inteiro começa a ignorar o canal de alertas. Alert fatigue não é um problema de configuração — é um problema de filosofia. A abordagem correta começa com uma pergunta: o que o usuário está experimentando agora? SLO-based alerting responde a essa pergunta de forma direta, mensurável, e com muito menos ruído do que threshold alerting.

Threshold Alerting vs SLO-based Alerting

Threshold Alerting — O problema

A abordagem clássica: "alerte quando a métrica cruzar X". Error rate acima de 1%? Alerta. CPU acima de 80%? Alerta. Latência acima de 500ms? Alerta. Simples de configurar, mas com problemas sérios em produção:

SLO-based Alerting — A abordagem correta

SLO (Service Level Objective) define o nível de confiabilidade prometido aos usuários. Um SLO típico: "99.9% das requests devem completar com sucesso em menos de 500ms, medido em janela rolling de 30 dias". O error budget é o que sobra: 0.1% × 30 dias × 24h × 60min = 43.2 minutos de downtime permitido no mês.

Alertar com base em SLOs significa alertar quando o consumo do error budget está em ritmo que vai esgotar o budget antes do fim do período — não quando uma métrica cruzou um threshold arbitrário. Isso vincula o alerta diretamente ao impacto no usuário.

SLI · SLO · SLA

SLI (Service Level Indicator): a métrica específica que você mede — proporção de requests com sucesso, latência P99, disponibilidade. SLO (Service Level Objective): o objetivo sobre o SLI que o time se compromete internamente: "error rate < 0.1% em 30 dias". SLA (Service Level Agreement): o contrato legal/comercial com consequências financeiras se violado — geralmente mais permissivo que o SLO interno (se SLO é 99.9%, SLA pode ser 99.5%), criando margem de segurança para reagir antes de quebrar o contrato com o cliente.

Burn Rate Alerts

Burn rate é a velocidade com que o error budget está sendo consumido, normalizada pela velocidade "normal" de consumo. Burn rate 1 = consumo exatamente na taxa esperada (o budget dura o período completo). Burn rate 14.4 = budget esgota em 30/14.4 ≈ 2 dias.

O Problema de uma Única Janela

Alertar com burn rate alto em janela curta (1h) captura incidentes rápidos e graves, mas dispara para spikes temporários de 10 minutos que se autorresolverem. Alertar em janela longa (6h) é mais estável mas reage tarde demais para incidentes rápidos que consomem muito budget em pouco tempo. A solução é exigir que o burn rate esteja alto em duas janelas simultâneas: uma longa (para confirmar que não é spike) e uma curta (para confirmar que ainda está ativo).

PromQL — burn rate com múltiplas janelas (Google SRE Workbook approach)
# SLO: 99.9% success rate, error budget: 0.1% por 30 dias
# Burn rate = taxa atual de consumo / taxa normal de consumo

# Alerta de alta urgência (page imediato):
# burn rate > 14.4x em DUAS janelas (1h longa + 5m curta)
- alert: ErrorBudgetBurnFast
  expr: |
    (
      rate(http_requests_total{status=~"5.."}[1h])
      / rate(http_requests_total[1h]) > (14.4 * 0.001)
    ) and (
      rate(http_requests_total{status=~"5.."}[5m])
      / rate(http_requests_total[5m]) > (14.4 * 0.001)
    )
  for: 2m
  labels:
    severity: page
    team: platform
  annotations:
    summary: "High error budget burn rate"
    description: >
      Error budget consumindo a {{ $value | humanizePercentage }} de erro.
      Burn rate 14.4x: budget esgota em menos de 2 dias.

# Alerta de baixa urgência (ticket/slack):
# burn rate > 6x em janela longa (6h + 30m)
- alert: ErrorBudgetBurnSlow
  expr: |
    (
      rate(http_requests_total{status=~"5.."}[6h])
      / rate(http_requests_total[6h]) > (6 * 0.001)
    ) and (
      rate(http_requests_total{status=~"5.."}[30m])
      / rate(http_requests_total[30m]) > (6 * 0.001)
    )
  for: 15m
  labels:
    severity: ticket
    team: platform
  annotations:
    summary: "Elevated error budget burn rate"
    description: "Burn rate 6x em janela de 6h. Budget em risco se mantiver."

Burn Rate Thresholds Práticos

SeveridadeBurn RateJanelasBudget Esgota emAção
Page (crítico)> 14.4×1h + 5m~2 diasDespertar on-call imediatamente
Page (urgente)> 6×6h + 30m~5 diasDespertar on-call se fora do horário
Ticket (baixa)> 3×24h + 6h~10 diasCriar ticket, resolver no próximo dia útil
Info> 1×72h< 30 diasMonitorar no dashboard semanal

Alertmanager

O Alertmanager (parte do ecossistema Prometheus) recebe alertas disparados pelo Prometheus e é responsável por: deduplicação, agrupamento, silenciamento, inibição, e roteamento para receivers (PagerDuty, OpsGenie, Slack, email). A separação entre "avaliar alertas" (Prometheus) e "gerenciar notificações" (Alertmanager) permite tratar a lógica de notificação como configuração independente da lógica de alerting.

Conceitos Fundamentais

alertmanager.yaml — routing, grouping e inibição
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 30s       # aguarda antes de enviar para agrupar alertas chegando juntos
  group_interval: 5m    # intervalo mínimo entre notificações do mesmo grupo
  repeat_interval: 4h   # reenviar se ainda ativo após 4h
  receiver: default-slack

  routes:
    # Page de alta urgência → PagerDuty
    - matchers:
        - severity = page
      receiver: pagerduty-critical
      continue: false

    # Alertas de banco → time de dados
    - matchers:
        - team = data
      receiver: slack-data-team
      group_by: ['alertname', 'database']

    # Staging → apenas Slack, nunca page
    - matchers:
        - environment = staging
      receiver: slack-dev-channel

receivers:
  - name: pagerduty-critical
    pagerduty_configs:
      - routing_key: ${PAGERDUTY_INTEGRATION_KEY}
        severity: critical

  - name: slack-data-team
    slack_configs:
      - api_url: ${SLACK_WEBHOOK_DATA}
        channel: '#alerts-data'
        send_resolved: true

  - name: default-slack
    slack_configs:
      - api_url: ${SLACK_WEBHOOK_DEFAULT}
        channel: '#alerts-platform'
        send_resolved: true

# Inibição: se datacenter alert ativo, inibe alerts de serviços individuais do mesmo cluster
inhibit_rules:
  - source_matchers:
      - alertname = DatacenterDown
    target_matchers:
      - severity =~ "warning|page"
    equal: ['cluster']

Alert Fatigue — O Maior Problema de On-call

Alert fatigue ocorre quando o volume ou frequência de alertas é alto o suficiente para que os engenheiros comecem a ignorá-los — consciente ou inconscientemente. O estado mais perigoso: alertas ativos que ninguém olha, porque o time aprendeu que "eles sempre disparam". A consequência lógica é um incidente real passando despercebido em meio ao ruído.

Sinais de Alert Fatigue

Como Combater

o teste do alerta

Rob Ewaschuk (Google, 2013): um bom alerta responde "sim" a três perguntas: (1) Este alerta detecta algo que impacta usuários agora? (2) A pessoa que recebe precisa agir urgentemente? (3) A ação requerida não pode ser automatizada? Se a resposta a qualquer uma for "não", o alerta precisa ser reformulado ou eliminado.

Alertas vs Tickets vs Dashboards

TipoQuando usarCanalExemplo
Page (urgente)Impacto ativo em usuários agora, requer ação imediataPagerDuty/OpsGenieError rate > 1% por 5min
Alerta de atençãoDegradação detectada, pode aguardar horas úteisSlack #alertsP99 aumentando, ainda dentro do SLO
TicketTendência preocupante, agir no próximo sprintJira/LinearBurn rate 2× por 24h
DashboardInformação para revisão proativaGrafanaError budget restante, deployment freq

On-call Sustentável

Rotação e Responsabilidade

On-call sustentável requer time grande o suficiente para rotação com intervalo mínimo de 1 semana por engenheiro. Google SRE Book recomenda: máximo de 25% do tempo de trabalho em atividades operacionais (on-call ativo + postmortems + toil). Com menos de 6 pessoas em rotação em uma semana de 7 dias, algum engenheiro está on-call por mais de uma semana seguida em algum momento — isso é insustentável em médio prazo.

Runbooks Acionáveis

Runbooks são o que torna on-call sustentável para quem não é expert em cada serviço. Um bom runbook contém: link para o dashboard relevante, causas prováveis em ordem de frequência, passos de diagnóstico com comandos concretos (não "verifique os logs" — kubectl logs -l app=order-service --tail=100 | grep ERROR), ações de mitigação com rollback se aplicável, e quando escalar e para quem.

Postmortem Blameless

Postmortem blameless é a prática de analisar incidentes sem culpar indivíduos — o foco é em falhas de sistema, processo e tooling. O postmortem documenta: linha do tempo, causa raiz técnica e de processo, impacto quantificado, o que foi feito de bem, o que falhou, e action items concretos com dono e prazo. Action items sem dono e prazo definidos nunca são executados.

Template de Postmortem Blameless
# Postmortem: [Título do Incidente]
**Data**: 2026-05-09
**Duração**: 14:23 - 16:47 UTC (2h24min)
**Impacto**: ~12% dos usuários receberam erro 503 no checkout
**Severity**: SEV-2

## Linha do Tempo
- 14:23 — Alertmanager disparou ErrorBudgetBurnFast
- 14:25 — Engenheiro on-call reconheceu o alerta
- 14:31 — Identificado: deploy de 14:18 alterou pool de conexões DB
- 14:45 — Rollback iniciado
- 15:02 — Rollback completado, error rate normalizado
- 16:47 — Monitoramento confirmou estabilidade, incidente fechado

## Causa Raiz
Deploy do PR #1842 reduziu max_connections do pool de 50 para 5
(erro de configuração em values.yaml). Sob carga normal, o pool saturou
causando timeouts que se propagaram para o checkout.

## Por que não foi detectado antes?
- Teste de staging usa mock do DB, não detecta saturação de pool
- Code review não incluiu revisão de mudanças em values.yaml

## O que foi bem
- Alerta disparou dentro de 5min do início do impacto
- Rollback executado dentro de 14min do alerta

## Action Items
| Item | Dono | Prazo |
|------|------|-------|
| Adicionar test de pool de conexão em staging | @camila | 2026-05-16 |
| PR checklist: mudanças em values.yaml requerem review de infra | @lucas | 2026-05-12 |
| Aumentar coverage de smoke tests pós-deploy | @ana | 2026-05-30 |

Alerting na Prática — C#, Python e Go

C# — regras de alerta para ASP.NET Core
# prometheus/rules/aspnetcore.yml
groups:
  - name: aspnetcore_slo
    interval: 1m
    rules:
      # SLI: success rate (excluindo 4xx esperados como not found)
      - record: job:http_request_success:rate5m
        expr: |
          sum(rate(http_server_request_duration_seconds_count{
            job="order-service",
            http_response_status_code!~"4.."
          }[5m])) by (job)
          /
          sum(rate(http_server_request_duration_seconds_count{
            job="order-service"
          }[5m])) by (job)

      # Burn rate alto → page
      - alert: OrderServiceHighErrorBurn
        expr: |
          (
            1 - job:http_request_success:rate5m{job="order-service"}
          ) > (14.4 * 0.001)
        for: 5m
        labels:
          severity: page
          team: platform
          service: order-service
        annotations:
          summary: "Order Service: high error budget burn"
          runbook_url: "https://wiki.internal/runbooks/order-service-errors"
          description: >
            Error rate {{ $value | humanizePercentage }} excede burn
            rate de 14.4x. Budget esgota em menos de 2 dias.

      # Latência P99 acima do SLO
      - alert: OrderServiceHighLatency
        expr: |
          histogram_quantile(0.99,
            sum(rate(http_server_request_duration_seconds_bucket{
              job="order-service",
              http_route="/api/orders"
            }[5m])) by (le)
          ) > 1.0
        for: 10m
        labels:
          severity: warning
          team: platform
        annotations:
          summary: "Order Service: P99 latency > 1s"
          description: "P99 em {{ $value | humanizeDuration }}"

ASP.NET Core com prometheus-net gera http_server_request_duration_seconds automaticamente via UseHttpMetrics(). Labels incluem http_route com o template do path (não o path real), o que permite agrupar por endpoint sem cardinalidade explosiva.

Python — SLO alerting para FastAPI + error budget remaining
# prometheus/rules/fastapi.yml
groups:
  - name: fastapi_slo
    interval: 1m
    rules:
      - record: job:http_requests_success:rate5m
        expr: |
          sum(rate(http_request_duration_seconds_count{
            job="api-service",
            status!~"5.."
          }[5m])) by (job)
          /
          sum(rate(http_request_duration_seconds_count{
            job="api-service"
          }[5m])) by (job)

      # Error budget restante na janela de 30 dias
      # 1 - (taxa_de_erro_realizada / slo_error_rate)
      - record: job:error_budget_remaining:ratio
        expr: |
          1 - (
            (1 - avg_over_time(job:http_requests_success:rate5m[30d]))
            / 0.001  # 1 - 0.999 SLO target
          )

      # Alerta quando budget abaixo de 25%
      - alert: ErrorBudgetLow
        expr: job:error_budget_remaining:ratio < 0.25
        for: 0m  # urgente — budget já baixo
        labels:
          severity: warning
        annotations:
          summary: "Error budget below 25%"
          description: >
            Apenas {{ $value | humanizePercentage }} de budget restante.
            Evite deployments de alto risco neste período.

  - name: celery_workers
    rules:
      - alert: CeleryWorkerDown
        expr: celery_workers_active == 0
        for: 2m
        labels:
          severity: page
        annotations:
          summary: "Todos os workers Celery estão inativos"
          runbook_url: "https://wiki.internal/runbooks/celery-down"

avg_over_time sobre a métrica gravada (recorded rule) é mais eficiente do que recalcular a janela de 30 dias a cada evaluation. Recorded rules são pré-computadas e armazenadas pelo Prometheus como séries temporais.

Go — burn rate com routing dinâmico por team label
# prometheus/rules/go_services.yml
groups:
  - name: go_service_slos
    interval: 30s
    rules:
      # Recorded rule: success rate por serviço e endpoint
      - record: service:http_success_rate:rate5m
        expr: |
          sum by (service, http_handler) (
            rate(http_requests_total{
              job=~".*-service",
              status_code!~"5.."
            }[5m])
          )
          /
          sum by (service, http_handler) (
            rate(http_requests_total{job=~".*-service"}[5m])
          )

      # Burn rate alert com dupla janela
      - alert: ServiceHighErrorBurnRate
        expr: |
          (1 - service:http_success_rate:rate5m) > (14.4 * 0.001)
          and
          (
            1 - sum by (service, http_handler)(
              rate(http_requests_total{status_code!~"5.."}[5m])
            ) / sum by (service, http_handler)(
              rate(http_requests_total[5m])
            )
          ) > (14.4 * 0.001)
        for: 2m
        labels:
          severity: page
          # label 'team' vem do service discovery → routing no Alertmanager
        annotations:
          summary: >
            {{ $labels.service }}/{{ $labels.http_handler }}: burn crítico
          description: >
            Error rate {{ $value | humanizePercentage }}.

# alertmanager.yml — routing por team label vindo dos targets
route:
  routes:
    - matchers:
        - team = payments
      receiver: pagerduty-payments
      group_by: [alertname, service]
    - matchers:
        - team = platform
      receiver: pagerduty-platform

Labels nos alvos do Prometheus (via service discovery ou static_configs) são propagados automaticamente para os alertas — permite routing no Alertmanager sem hardcodar a label no rules file. Cada serviço declara seu team no scrape config.

Decisões de engenharia

Quando migrar de threshold para SLO-based alerting?

Quando threshold alerts causarem mais de 2-3 pages não acionáveis por semana, ou quando o time começar a ignorar alertas sistematicamente. SLO alerts requerem definir SLOs explicitamente — o processo de definição em si é valioso porque força alinhamento sobre o que "bom" significa para cada serviço. Se você não sabe o baseline atual do serviço, comece medindo por 2-4 semanas antes de definir o SLO. Nunca defina um SLO mais agressivo do que o baseline atual medido — você terá alertas constantes desde o primeiro dia.

PagerDuty/OpsGenie vs alertas só no Slack?

Alertas só no Slack: aceitável para startups pequenas sem SLA crítico e equipes que monitoram o canal ativamente. O problema do Slack: mensagens se perdem no fluxo, não há escalação automática, e não há histórico estruturado de incidentes. PagerDuty/OpsGenie adicionam: escalation policies (se não respondido em Xmin, escala para o próximo), schedule management com rotação automática, e histórico de incidentes pesquisável. O custo ($) é justificado assim que um incidente perdido no Slack (ou o custo de acordar a pessoa errada às 3am) custa mais que a ferramenta.

Quantos alertas por serviço é demais?

Não há número fixo, mas um critério prático: se durante a criação do alerta você pensou "vou adicionar por precaução" — não adicione. Todo alerta deve ter uma história clara: "este alerta dispara quando X acontece, e quando isso acontece o engenheiro precisa fazer Y imediatamente". Comece com os 4 golden signals (latência, traffic, errors, saturation) e adicione alertas apenas quando a ausência deles teria causado impacto não detectado em um incidente real. Para um serviço CRUD típico, 2-4 alertas de page são suficientes.

Como definir o SLO certo?

Não comece pela meta aspiracional — comece medindo o que você tem hoje por 30 dias. Se o serviço está em 99.5% availability hoje, um SLO de 99.9% é irreal sem investimento significativo em confiabilidade. Um SLO ligeiramente abaixo do estado atual (99.3% se você está em 99.5%) é um bom ponto de partida — é alcançável hoje e dá espaço para melhorar sem alertas constantes. O SLO deve também refletir o que o usuário percebe: se 0.1% de erros afeta usuários VIP e 2% de erros afeta usuários gratuitos, eles precisam de SLOs diferentes.

Como praticar

  1. Implemente SLO-based alerting completo para um serviço HTTP simples (pode ser uma app de exemplo): defina um SLI de success rate, calcule o error budget para um SLO de 99.9% em 30 dias, e configure dois alertas de burn rate no Prometheus — um de alta urgência (14.4× em 1h+5m) e um de baixa urgência (6× em 6h+30m). Dispare erros artificialmente em diferentes intensidades e verifique quais alertas disparam.
    Critério: um spike de 10% de erros por 3 minutos não dispara o alerta de alta urgência; um erro rate de 5% sustentado por 10 minutos dispara o alerta de alta urgência; um erro rate de 2% por 1 hora dispara o alerta de baixa urgência; os dois alertas têm runbook_url preenchido.
  2. Configure Alertmanager com routing, grouping e inibição: crie três receivers (PagerDuty simulado via webhook local, Slack-dev para staging, Slack-prod para produção), configure grouping por alertname+service, adicione uma regra de inibição que suprime alertas de serviço quando um alerta de infraestrutura do mesmo cluster está ativo. Valide que um alerta de infraestrutura ativo inibe os alertas de serviço downstream.
    Critério: um alerta de page vai para o receiver correto (PagerDuty); alertas em staging vão apenas para Slack-dev; um alerta de "DatabaseClusterDown" inibe os alertas dos serviços que dependem do DB; o histórico no Alertmanager UI mostra o silence/inhibition correto.
  3. Conduza uma triagem de alert fatigue: pegue um serviço existente (ou crie um cenário simulado com 10+ alertas) e aplique o "teste de três perguntas" de Rob Ewaschuk a cada alerta. Documente quais alertas passam, quais falham, e o motivo. Para os que falham, proponha uma alternativa (rebaixar para ticket, remover, transformar em dashboard).
    Critério: todos os alertas foram avaliados; pelo menos 30% foram identificados como candidatos a remoção ou rebaixamento; cada decisão está documentada com justificativa; a "acionabilidade" estimada pós-triagem é > 80%.
  4. Escreva um runbook completo para um alerta existente: escolha um alerta de burn rate e escreva o runbook com link para dashboard relevante, causas prováveis em ordem de frequência, e pelo menos 3 passos de diagnóstico com comandos kubectl/PromQL/CLI concretos. Valide o runbook fazendo um colega executá-lo durante um incidente simulado sem sua ajuda.
    Critério: o colega consegue diagnosticar a causa simulada seguindo apenas o runbook, sem perguntar; cada passo de diagnóstico tem um comando concreto (não "verifique os logs"); o runbook inclui critério de escalação (quando e para quem escalar); o tempo médio de diagnóstico é < 15 minutos.
  5. Escreva um postmortem blameless para um incidente real ou simulado: use o template com linha do tempo, causa raiz técnica e de processo, impacto quantificado, e pelo menos 3 action items com dono e prazo. Valide que nenhuma linguagem do postmortem culpa um indivíduo — use revisão por pares.
    Critério: o postmortem não contém linguagem de culpa individual (termos como "o engenheiro X deveria ter" devem ser refraseados como "o processo de review não detectou"); causa raiz inclui tanto causa técnica quanto causa de processo; todos os action items têm dono nomeado e prazo em data absoluta; pelo menos um action item melhora o alerting ou o runbook do serviço afetado.

Perguntas de entrevista

    O que é burn rate de error budget e por que é melhor que threshold alerting?

    Error budget é o quanto o serviço pode falhar dentro do período do SLO. Para um SLO de 99.9% em 30 dias: 0.1% × 30d × 24h × 60min = 43.2 minutos de downtime permitido. Burn rate é a velocidade de consumo normalizada: burn rate 1 = consumo exatamente na taxa esperada (budget dura o período); burn rate 14.4 = consumo 14.4× mais rápido, budget esgota em ~2 dias.

    Burn rate é superior ao threshold porque: (1) considera duração — 1% de erro por 5 minutos vs 1% por 4 horas têm impactos completamente diferentes no budget; (2) alinha com impacto ao usuário — você alerta quando o acúmulo de erros é significativo, não quando uma métrica cruzou um número arbitrário; (3) reduz falsos positivos — spikes curtos não disparam alertas de alta urgência (a janela curta + longa simultânea filtra spikes); (4) força clareza sobre SLOs — para definir burn rate você precisa definir um SLO, e esse processo força alinhamento sobre o que "confiabilidade suficiente" significa para cada serviço.

    Como você estruturaria alerting para um time de 8 engenheiros com 5 microserviços?

    Com 8 engenheiros e 5 serviços, o risco principal é alert fatigue — poucos engenheiros para absorver muito ruído. Estruturaria em camadas:

    (1) SLOs por serviço: definiria um SLO para cada serviço baseado no baseline atual medido por 30 dias, não em metas ideais. (2) Alertas em duas camadas: page (PagerDuty, burn rate > 14.4× em 1h) e ticket (Slack + Jira, burn rate > 3× em 24h). (3) Grouping agressivo: usar grouping no Alertmanager para que um outage que afeta 3 endpoints gere 1 notificação consolidada, não 3. (4) Inibição de alertas causais: se o DB está down, inibir alertas de todos os serviços que dependem do DB. (5) Runbook obrigatório: nenhum alerta sem runbook — enforced via PR review. (6) Review semanal de 15min: quantos alertas dispararam, quantos foram acionáveis. Com 8 pessoas, rotação de on-call seria 1 pessoa por semana em turno, com handoff documentado no início do turno e postmortem para qualquer SEV-1 ou SEV-2.

    Qual a diferença entre SLI, SLO e SLA?

    SLI (Service Level Indicator): a métrica específica que você mede. Ex: "proporção de HTTP requests completadas com sucesso (2xx/3xx) no último minuto". O SLI é um número entre 0 e 1 (ou percentual). Múltiplos SLIs podem ser combinados em um SLO composto (ex: success rate AND latência P99 < 500ms).

    SLO (Service Level Objective): o alvo de qualidade que o time se compromete internamente a atingir. Ex: "SLI de success rate deve ser ≥ 99.9%, medido em janela rolling de 30 dias". O SLO é interno — é o contrato do time com ele mesmo e com os stakeholders internos. A regra de ouro: o SLO deve ser alcançável hoje, e viola-se internamente um SLO antes de violar o SLA, dando tempo de reagir.

    SLA (Service Level Agreement): o contrato legal/comercial com consequências (créditos, penalidades, rescisão) caso não seja cumprido. Geralmente mais permissivo que o SLO — se o SLO interno é 99.9%, o SLA pode ser 99.5%, criando uma margem de 0.4% para absorver variações antes de impactar o cliente comercialmente. O SLA é negociado com clientes e definido com base no que o sistema pode genuinamente entregar.

    Como você identificaria e eliminaria alert fatigue no time?

    Em três frentes: (1) Diagnóstico quantitativo: pull do histórico de alertas das últimas 4 semanas — quantos dispararam, quantos resultaram em ação imediata, quantos foram silenciados/ignorados. Alertas com acionabilidade < 50% são candidatos prioritários à eliminação ou rebaixamento. (2) Triage de alertas existentes: para cada alerta, aplicar o "teste de três perguntas" (impacto ativo no usuário? ação urgente necessária? ação não pode ser automatizada?). Se qualquer resposta for não, o alerta não deveria ser page. (3) Processo contínuo: instaurar revisão semanal de 15min de alertas (retro focada especificamente em alertas da semana). Criar uma métrica de saúde do alerting: "% de pages que requereram ação imediata" — meta > 80%. Abaixo disso, há ruído demais. Por fim, exigir que qualquer novo alerta seja adicionado via PR com runbook incluído — o atrito do processo previne adição irresponsável de alertas.

    O que é um postmortem blameless e por que a cultura blameless é difícil de implementar?

    Postmortem blameless: análise de incidente que foca em falhas de sistema, processo e tooling — não em erros individuais. O pressuposto é que engenheiros tomam as melhores decisões possíveis com a informação disponível no momento. Se um engenheiro causou um incidente ao executar um comando "óbvio", a pergunta certa não é "por que ele fez isso?" mas "por que o sistema permitiu que esse comando causasse esse impacto?"

    Por que é difícil: (1) Pressão implícita por responsabilização — gestores e stakeholders frequentemente querem "quem causou" como resposta, e equipes aprendem a satisfazer essa expectativa mesmo em postmortems nominalmente blameless; (2) Auto-censura — engenheiros omitem detalhes embaraçosos por medo de consequências, o que compromete a causa raiz real; (3) Viés retrospectivo — após o incidente, as ações que levaram ao problema parecem óbvias, o que torna fácil culpar quem tomou essas decisões. A implementação requer: linguagem explicitamente revisada para remover culpa ("o engenheiro X deveria ter visto" → "o processo de review não sinalizou"), participação da gestão como guardiã da cultura, e postmortems de incidentes menores onde o risco de culpa é baixo para construir o hábito antes de incidentes graves.

Referências para aprofundar

  1. livro Site Reliability Engineering — Niall Richard Murphy, Betsy Beyer, Chris Jones, Jennifer Petoff (O'Reilly, 2016). sre.google/sre-book — Capítulos 4 (SLOs), 6 (Monitoring Distributed Systems), 11 (Being On-Call), 15 (Postmortem Culture). A fonte primária de SLO-based alerting e cultura de on-call sustentável.
  2. livro The Site Reliability Workbook — Betsy Beyer et al. (O'Reilly, 2018). sre.google/workbook — Capítulo "Alerting on SLOs" detalha os burn rate thresholds com múltiplas janelas (14.4×, 6×, 3×) e a matemática por trás. Leitura obrigatória após o SRE Book.
  3. livro Implementing Service Level Objectives — Alex Hidalgo (O'Reilly, 2020). Guia prático e completo de SLI/SLO/Error Budget — cobre desde a definição até a política de error budget para decisões de engenharia (quando parar deployments, quando priorizar confiabilidade vs features).
  4. paper My Philosophy on Alerting — Rob Ewaschuk (Google, 2013). docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q — O paper seminal com o "teste de três perguntas" para avaliar alertas. Curto, denso, vale a leitura completa.
  5. docs Alertmanager — Documentação oficial — Prometheus Project (2024). prometheus.io/docs/alerting/latest/alertmanager — Referência completa de configuração: routing tree, grouping, inhibition, silencing, receivers. Inclui exemplos de alertmanager.yaml para casos comuns.
  6. docs Prometheus Recording Rules — Prometheus Project (2024). prometheus.io/docs/prometheus/latest/configuration/recording_rules — Documentação de recording rules para pré-computar métricas usadas em alertas. Crítico para alertas de burn rate eficientes (avg_over_time sobre janelas de 30 dias).
  7. artigo Error Budget Policy — Google Cloud Blog (2023). cloud.google.com/blog — Como usar o error budget como mecanismo de decisão: quando parar deployments, quando escalar equipe de SRE, quando priorizar confiabilidade. A política de error budget transforma SLOs de métrica em ferramenta de governança.
  8. artigo Meaningful Availability — Tamara Munzner, Hauer et al. (USENIX NSDI, 2020). usenix.org/conference/nsdi20 — Paper da Google sobre como medir disponibilidade de forma que reflita a experiência real do usuário (user-facing availability vs uptime de infra). Fundamenta por que SLIs devem ser medidos do ponto de vista do cliente.
  9. artigo Incident Response at Slack — Slack Engineering Blog (2022). slack.engineering — Como a Slack estrutura on-call, severity levels, escalation paths e postmortems. Bom estudo de caso de uma empresa que escalonou on-call de startup para empresa com SLA crítico.
  10. artigo How to Avoid On-call Burnout — Increment Magazine (2021). increment.com — Perspectiva humana sobre on-call sustentável: rotação, compensação, limites de interrupção, e como a cultura de engenharia afeta o bem-estar de quem faz on-call. Complemento necessário ao lado técnico do SRE Book.
  11. docs PagerDuty Incident Response Guide — PagerDuty (2024). response.pagerduty.com — Guia prático de resposta a incidentes: severity levels, escalation policies, comunicação durante incidentes, e templates de postmortem. Referência operacional para times que usam PagerDuty.
  12. docs OpenSLO Specification — OpenSLO Project (2024). github.com/OpenSLO/OpenSLO — Standard para declarar SLOs como código (YAML), permitindo versionamento, revisão via PR, e geração automática de alertas. Integra com Grafana, Prometheus e ferramentas de SLO como Pyrra e Sloth.