SLO e error budget: confiabilidade de APIs com Prometheus
SLI (Service Level Indicator), SLO (Service Level Objective) e error budget são o vocabulário do Site Reliability Engineering para medir confiabilidade de forma objetiva. Em vez de "o sistema está lento", você diz "nosso P99 de latência está em 850ms e nosso SLO é 500ms — 68% do error budget foi consumido este mês".
Conceitos: SLI, SLO e error budget
Definir os três conceitos e como se relacionam:
# SLI (Service Level Indicator):
# → A métrica que mede o comportamento do serviço
# Exemplos:
# Disponibilidade: % de requisições bem-sucedidas (status 2xx/3xx)
# Latência: % de requisições que respondem em < 500ms
# Throughput: requisições processadas por segundo
# SLO (Service Level Objective):
# → A meta que você quer atingir para o SLI
# Exemplos:
# Disponibilidade: 99.9% das requisições devem ter status 2xx/3xx
# Latência: 95% das requisições devem responder em < 500ms
# Error budget:
# → O quanto de "não conformidade" é permitido
# 99.9% de disponibilidade = 0.1% de erro permitido
# Em 30 dias: 0.001 × 30 × 24 × 60 = 43 minutos de downtime permitido
# Em 7 dias: 0.001 × 7 × 24 × 60 = 10 minutos de downtime permitido
# Quando o error budget acaba:
# → Parar novos deploys até o fim do período
# → Focar em confiabilidade, não em features
# → Isso alinha incentivos entre Dev e Ops
# Conversão disponibilidade → tempo de downtime por mês:
# 99.0% → 7.2h
# 99.5% → 3.6h
# 99.9% → 43min (three nines — padrão para a maioria das SaaS B2B)
# 99.99% → 4.3min (four nines — para serviços críticos)Calcular SLI de disponibilidade com Prometheus
Queries PromQL para medir disponibilidade em tempo real:
# SLI de disponibilidade — % de requisições bem-sucedidas:
# "Boas" = 2xx e 3xx | "Ruins" = 5xx
# (4xx geralmente são erros do cliente, não do serviço)
# Taxa de disponibilidade nas últimas 24h:
sum(rate(http_request_duration_seconds_count{status_code!~"5.."}[24h]))
/
sum(rate(http_request_duration_seconds_count[24h]))
# Error rate (1 - disponibilidade):
sum(rate(http_request_duration_seconds_count{status_code=~"5.."}[24h]))
/
sum(rate(http_request_duration_seconds_count[24h]))
# SLI de latência — % de requisições dentro do SLO de tempo:
# SLO: 95% das requisições em < 500ms
sum(rate(http_request_duration_seconds_bucket{le="0.5"}[1h]))
/
sum(rate(http_request_duration_seconds_count[1h]))
# Janela deslizante de 30 dias (mais precisa para error budget mensal):
sum(rate(http_request_duration_seconds_count{status_code!~"5.."}[30d]))
/
sum(rate(http_request_duration_seconds_count[30d]))
# Recording rule para pré-computar (performance):
# rules/slo.yml:
# - record: job:sli_disponibilidade:ratio_rate1h
# expr: |
# sum(rate(http_request_duration_seconds_count{status_code!~"5.."}[1h]))
# / sum(rate(http_request_duration_seconds_count[1h]))Calcular e monitorar o error budget
Acompanhar quanto do orçamento de erros foi consumido:
# Recording rules para SLO — definir uma vez e usar em múltiplos lugares:
# prometheus/rules/slo.yml:
groups:
- name: slo-nodejs-api
interval: 1m
rules:
# SLI: taxa de sucesso (janelas de tempo diferentes para alertas):
- record: job:http_sli_sucesso:rate5m
expr: |
sum(rate(http_request_duration_seconds_count{job="nodejs-api",status_code!~"5.."}[5m]))
/ sum(rate(http_request_duration_seconds_count{job="nodejs-api"}[5m]))
- record: job:http_sli_sucesso:rate1h
expr: |
sum(rate(http_request_duration_seconds_count{job="nodejs-api",status_code!~"5.."}[1h]))
/ sum(rate(http_request_duration_seconds_count{job="nodejs-api"}[1h]))
- record: job:http_sli_sucesso:rate30d
expr: |
sum(rate(http_request_duration_seconds_count{job="nodejs-api",status_code!~"5.."}[30d]))
/ sum(rate(http_request_duration_seconds_count{job="nodejs-api"}[30d]))
# Calcular error budget consumido:
# SLO_TARGET = 0.999 (99.9%)
# error_budget_total = 1 - SLO_TARGET = 0.001
# error_budget_consumido = (1 - SLI) / (1 - SLO_TARGET) * 100
# Query no Grafana — % de error budget consumido no mês:
# (1 - job:http_sli_sucesso:rate30d) / (1 - 0.999) * 100
# Exemplo de resultado:
# SLI últimos 30d = 0.9995 (99.95%)
# Error budget consumido = (1 - 0.9995) / (1 - 0.999) * 100 = 50%
# → 50% do budget foi consumido, 50% restaAlertas baseados em burn rate do error budget
Detectar quando o error budget está sendo consumido rápido demais:
# Alertas de burn rate — alertar quando o budget está sendo queimado em ritmo que,
# se mantido, vai esgotar o budget antes do fim do mês.
# burn_rate = taxa atual de erro / taxa de erro permitida pelo SLO
# Se burn_rate = 1: consumindo budget exatamente no ritmo
# Se burn_rate = 10: consumindo 10x mais rápido → budget esgota em 3 dias (30/10)
# SLO = 99.9% → error_rate_permitida = 0.001
# alerts/slo.yml:
groups:
- name: slo-burn-rate
rules:
# CRÍTICO: burn rate > 14.4x nas últimas 1h
# (esgota o budget mensal em ~2 dias)
- alert: SloBurnRateCritico
expr: |
(1 - job:http_sli_sucesso:rate5m) / 0.001 > 14.4
AND
(1 - job:http_sli_sucesso:rate1h) / 0.001 > 14.4
for: 2m
labels:
severity: critical
slo: disponibilidade
annotations:
summary: "SLO: burn rate crítico — budget esgotará em ~2 dias"
description: |
Burn rate atual: {{ $value | printf "%.1f" }}x.
Error rate: {{ with query "1 - job:http_sli_sucesso:rate5m" }}{{ . | first | value | humanizePercentage }}{{ end }}.
# WARNING: burn rate > 6x nas últimas 6h
# (esgota o budget mensal em ~5 dias)
- alert: SloBurnRateAlto
expr: |
(1 - job:http_sli_sucesso:rate5m) / 0.001 > 6
for: 15m
labels:
severity: warning
slo: disponibilidade
annotations:
summary: "SLO: burn rate elevado — atenção ao error budget"Dashboard de SLO no Grafana
Painel visual de SLO com semáforo e histórico de compliance:
# Painéis Grafana para SLO:
# 1. Stat panel — SLI atual (com threshold colorido):
# Query: job:http_sli_sucesso:rate30d * 100
# Thresholds:
# verde: >= 99.9 (dentro do SLO)
# amarelo: 99.5 a 99.9 (dentro do budget mas atenção)
# vermelho: < 99.5 (violação do SLO)
# Unit: percent
# 2. Stat panel — Error budget restante %:
# Query: (1 - (1 - job:http_sli_sucesso:rate30d) / 0.001) * 100
# Thresholds:
# verde: > 50%
# amarelo: 10% a 50%
# vermelho: < 10%
# 3. Time series — Burn rate ao longo do tempo:
# Query: (1 - job:http_sli_sucesso:rate5m) / 0.001
# Linha de referência em y=1 (taxa normal) e y=6 (alerta)
# 4. Time series — SLI ao longo do mês (comparar com SLO):
# Query: job:http_sli_sucesso:rate1h * 100
# Linha de referência em y=99.9 (SLO target)
# Importar template pronto: Grafana ID 14348 — SLO Dashboard
# Documentar o SLO em arquivo de configuração:
# slos/nodejs-api.yml:
# service: nodejs-api
# slos:
# - name: disponibilidade
# indicator: taxa de requisições 2xx/3xx
# target: 99.9
# window: 30d
# - name: latencia
# indicator: P95 < 500ms
# target: 95.0
# window: 30d$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS para Node.js em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.
Perguntas frequentes
Conteúdos relacionados