Durante anos, a indústria de software tratou disponibilidade como uma porcentagem vaga — "o sistema fica disponível 99.9% do tempo" — sem definir com precisão o que isso significa. Disponibilidade de quê? Medida como? Em que janela de tempo? Vista de onde? Para qual cliente? A ausência de precisão produzia contratos inúteis: uma empresa que prometia "99.9% uptime" mas excluía manutenções planejadas, janelas de madrugada, e falhas parciais de componentes raramente estava prometendo 99.9% de nada relevante para o usuário.
O framework SLI/SLO/SLA — Service Level Indicator, Service Level Objective, Service Level Agreement — foi desenvolvido dentro do Google no início dos anos 2000, formalizado em livro no Google SRE Book (Beyer et al., O'Reilly, 2016, capítulos 4 e 5), e desde então tornou-se o vocabulário padrão da indústria para articular confiabilidade de sistemas. Não é burocracia corporativa: é a diferença entre "achamos que o sistema está saudável" e "sabemos que o sistema está saudável, e temos número para provar".
A hierarquia é simples mas cada camada tem peso distinto. O SLI é a medida — o número bruto extraído do sistema. O SLO é o alvo sobre esse número — o comprometimento interno do time. O SLA é o contrato sobre o alvo — o que foi prometido ao cliente com consequências formais para descumprimento. Confundir as três camadas é receita para SLAs impossíveis, SLOs que ninguém olha, e SLIs que medem a coisa errada.
Este conceito percorre cada camada em profundidade: como escolher SLIs que reflitam a experiência real do usuário (e não a saúde interna do servidor), como calibrar SLOs que criem pressão saudável sem paralisar velocidade, e como manter buffer entre SLO interno e SLA externo de modo que o time sempre saiba quando está em risco antes que o cliente perceba.
Service Level Indicator — a medida
Um SLI é uma métrica quantitativa que representa algum aspecto do nível de serviço provido. A palavra-chave é "nível de serviço" — não saúde interna do servidor, não latência de um componente específico, mas a experiência do usuário final com o sistema. Essa distinção importa muito na prática. CPU de 80% não é SLI. Latência P99 de requisições HTTP vistas pelo usuário — isso é SLI.
O Google SRE Book descreve quatro categorias de SLI que cobrem a maior parte dos sistemas de software:
Availability (disponibilidade): fração de requisições bem-sucedidas sobre o total de requisições. Uma requisição bem-sucedida é definida pelo time — tipicamente, qualquer resposta HTTP que não seja 5xx, ou qualquer operação que não resulte em erro para o usuário. Exemplo: 99.95% das requisições ao endpoint /checkout retornam status 200 ou 4xx (não 5xx).
Latency (latência): fração de requisições que completam dentro de um limiar de tempo definido. Não é "latência média" — é uma distribuição. Exemplo: 95% das requisições ao endpoint /search completam em menos de 200ms; 99% completam em menos de 800ms. Usar médias é armadilha: uma média de 100ms pode esconder que 1% dos usuários espera 10 segundos.
Quality (qualidade): fração de requisições que retornam dados não-degradados. Relevante quando a API pode retornar resposta "parcial" — resultados de cache desatualizado, dados com campos faltando, recomendações genéricas em vez de personalizadas. Uma requisição tecnicamente bem-sucedida mas que entrega valor degradado pode ser contada como "ruim" para fins de SLI.
Coverage (cobertura): usado principalmente em sistemas de pipeline e processamento batch. Fração dos dados que foram processados corretamente dentro da janela esperada. Exemplo: 99.9% dos eventos de analytics são processados e disponíveis no dashboard em menos de 10 minutos após geração.
SLI deve ser medido do ponto de vista mais próximo possível do usuário. Se você tem métricas do load balancer, prefira-as às métricas do servidor de aplicação. Se você tem RUM (Real User Monitoring), prefira-o ao servidor. O usuário não vê latência de processo — ele vê latência de página, latência de API. Medir do servidor e reportar ao cliente como se fosse experiência de usuário é uma das formas mais comuns de SLI que mente.
Janelas de medição e agregação
SLIs são calculados sobre janelas de tempo. A escolha da janela altera profundamente o que o número significa. Duas estratégias principais:
Rolling window (janela deslizante): os últimos N dias, calculados continuamente. Se o SLI é calculado sobre os últimos 30 dias, uma falha que aconteceu há 29 dias ainda afeta o número de hoje, mas deixará de afetar amanhã. Rolling windows são mais estáveis e mais relevantes operacionalmente — o time sempre sabe "como está hoje em relação ao passado próximo".
Calendar window (janela calendário): o mês corrente, o trimestre corrente. Comum em SLAs com clientes (faturamento por mês). Tem o problema do "efeito reset" — no início de cada período, o budget está cheio independentemente do que aconteceu no período anterior. Uma empresa que tem falha grave no dia 1 do mês e não tem mais no dia 2 "recupera" o número até o fim do mês, mas o usuário que viveu a falha não sente essa recuperação.
A maioria dos times usa rolling windows para SLOs internos (melhor para operação) e calendar windows para SLAs externos (alinhado com faturamento). Manter os dois é válido — eles respondem perguntas diferentes.
Service Level Objective — o alvo interno
O SLO é o comprometimento interno do time sobre o SLI: "nosso SLO é que 99.9% das requisições ao checkout sejam bem-sucedidas, medido em rolling 30 dias". É o contrato do time consigo mesmo — não com o cliente, não com o legal. Isso é crucial: o SLO deve ser ambicioso o suficiente para criar pressão real, mas flexível o suficiente para permitir mudança.
A calibração do SLO é mais arte que ciência, mas algumas heurísticas consolidadas da literatura ajudam. A principal é: use os dados históricos como ponto de partida, não como destino. Se o sistema tem operado a 99.85% historicamente, um SLO de 99% é conservador demais (não cria pressão) e 99.99% é inatingível sem mudanças arquiteturais significativas. Um SLO de 99.9% — ligeiramente mais ambicioso que o histórico — cria a tensão produtiva certa.
SLOs definidos top-down ("o VP quer cinco noves") sem análise de viabilidade técnica são ilusões operacionais. 99.999% de disponibilidade significa no máximo 5.26 minutos de downtime por ano — para isso, você precisa de redundância ativa em múltiplas regiões, zero deploys que causem downtime, e zero dependências de terceiro sem fallback. Sistemas que prometem 99.999% sem infraestrutura correspondente mentem para si mesmos.
O que um SLO contém
Um SLO bem especificado tem quatro elementos: o SLI (o que mede), o target (o número alvo), a janela (o período de medição), e a fonte de dados (de onde a métrica vem). Exemplo completo:
SLO — Checkout API Availability
SLI: fração de requisições HTTP ao endpoint /v1/orders
que retornam status != 5xx
Target: ≥ 99.9%
Janela: rolling 30 dias
Fonte: nginx access logs (upstream_status), excluindo
requisições de health check (/health, /ready)
A exclusão importa. Health checks, bots de monitoramento, e tráfego sintético não representam usuários reais e devem ser filtrados. Da mesma forma, algumas categorias de erro genuíno podem ser excluídas: se um cliente envia uma requisição malformada (400), isso não é falha do serviço. Se um usuário não autenticado tenta acessar recurso protegido (401), isso não é falha do serviço. Apenas erros de servidor (5xx) geralmente contam como "requisição ruim" para fins de SLI de disponibilidade.
Múltiplos SLOs por serviço
Um serviço pode ter vários SLOs simultâneos medindo aspectos diferentes. O time do Google Search, por exemplo, tem SLOs separados para disponibilidade (fração de buscas que retornam resultado), latência (fração de buscas completadas em menos de Xms), e qualidade (fração de buscas que retornam resultado relevante, medido por métricas de engajamento). Cada SLO monitora um eixo diferente da experiência do usuário.
Para times que estão começando, a recomendação é começar com dois SLOs por serviço: um de disponibilidade e um de latência. Isso já captura as duas dimensões mais importantes da experiência do usuário sem criar overhead de monitoramento excessivo.
Service Level Agreement — o contrato externo
O SLA é o acordo com o cliente — geralmente com penalidades contratuais para descumprimento. Pode assumir formas diferentes: créditos no faturamento, penalidades em dinheiro, direito de rescisão de contrato. O que distingue SLA de SLO é a consequência formal.
A regra de ouro é que o SLA deve estar sempre acima do SLO por uma margem de segurança. Se o SLO interno é 99.9%, o SLA externo deve ser 99.5% ou 99% — nunca os mesmos 99.9%. Essa margem existe por razões práticas: o time precisa de espaço para investigar, corrigir, e se recuperar antes que o cliente seja atingido pelas consequências contratuais. Se SLO e SLA são iguais, cada violação de SLO é automaticamente uma violação de SLA — o que cria pressão punitiva que paralisa o time em vez de motivá-lo.
O SLA é o que você promete ao cliente. O SLO é o que você promete a si mesmo. O SLI é o que você mede. Nunca negocie o SLA com o cliente antes de saber se o SLO é atingível — e nunca defina o SLO sem ter o SLI instrumentado. A sequência correta é: instrumentar primeiro, medir por 4-8 semanas, calibrar SLO baseado em dados, depois negociar SLA com buffer.
SLAs em B2B vs B2C
Em produtos B2B (SaaS enterprise, APIs para parceiros), SLAs são contratos formais negociados por jurídico com valores específicos de crédito por período de downtime. AWS, por exemplo, publica SLAs detalhados por produto: EC2 com SLA de 99.99%, crédito de 10% se disponibilidade cair entre 99.0% e 99.99%, 30% se cair abaixo de 99.0%.
Em produtos B2C (aplicativos para usuários finais), SLAs são raros como contrato formal — nenhuma empresa de aplicativo móvel assina contrato com milhões de usuários individualmente. O que existe é um compromisso moral implícito, uma política pública de status (Statuspage.io, status.github.com), e eventualmente créditos ou reembolsos voluntários para usuários afetados por incidentes graves. A estrutura SLI/SLO ainda se aplica internamente com toda força — o SLA externo formal simplesmente não existe da mesma forma.
Escolhendo SLIs user-centric
A armadilha mais comum ao escolher SLIs é medir o que é fácil de medir (CPU, memória, erros de infraestrutura) em vez do que importa para o usuário. Um servidor com CPU a 90% não é problema se o usuário não percebe nenhuma degradação. Um servidor com CPU a 20% que está travado em deadlock é problema grave mesmo que a métrica de infraestrutura pareça saudável.
A abordagem user-centric começa com uma pergunta: "o que o usuário experimenta quando o sistema está saudável, e como sabemos que está saudável da perspectiva dele?" Para uma API de e-commerce: o usuário consegue completar um pedido? A página de produto carrega em tempo razoável? O carrinho persiste corretamente? Cada uma dessas perguntas mapeia para um SLI concreto.
Uma técnica útil é a customer journey mapping para SLIs: mapear as jornadas críticas do usuário (cadastrar, buscar, adicionar ao carrinho, finalizar compra, acompanhar pedido) e definir pelo menos um SLI para cada etapa crítica. Isso garante que o monitoramento cobre o que importa para o negócio.
Exemplo completo — e-commerce
| Jornada | SLI | SLO |
|---|---|---|
| Busca de produto | % requisições a /search com status 200 e latência < 300ms | 95% · rolling 7 dias |
| Página de produto | % requisições a /products/* com status 200 | 99.9% · rolling 30 dias |
| Checkout | % requisições a /orders com status 200 ou 400 (não 5xx) | 99.95% · rolling 30 dias |
| Processamento de pagamento | % transações confirmadas dentro de 5s | 99% · rolling 30 dias |
Note que o SLO de checkout (99.95%) é mais agressivo que o de busca (95%) — porque uma busca que falha é irritante, mas um checkout que falha é perda direta de receita. SLOs diferentes para partes diferentes do sistema refletem prioridades de negócio.
Burn rate e alertas baseados em SLO
Um dos avanços mais importantes do Google SRE Book foi formalizar alertas baseados em SLO em vez de alertas baseados em limiares estáticos. O problema de "alerte quando CPU > 80%" é que CPU alta nem sempre significa problema para o usuário — e CPU saudável nem sempre significa que o usuário está bem.
Alertas baseados em SLO observam a taxa de consumo do error budget (burn rate). Se o SLO é 99.9% em 30 dias, o error budget total é 0.1% × 30 dias × 24h = 43.2 minutos de downtime aceitável no mês. Um burn rate de 1× significa que o budget está sendo consumido exatamente na taxa que zeraría em 30 dias. Um burn rate de 6× significa que, se continuar, o budget estará esgotado em 5 dias.
O Google SRE Workbook (Fowler et al., 2018) recomenda dois alertas de burn rate complementares:
Alerta de queima rápida (fast burn): burn rate acima de 14.4× por mais de 1 hora. Isso significa que o budget mensal inteiro estará consumido em menos de 2 dias se a situação persistir. Requer ação imediata — provavelmente um incidente.
Alerta de queima lenta (slow burn): burn rate acima de 1× por mais de 6 horas. A situação não é urgente mas é insustentável — o budget estará esgotado antes do fim do período se não for corrigido. Requer investigação e ação em horas, não em minutos.
public class SloTracker
{
private readonly string _sloName;
private readonly double _target; // ex: 0.999
private readonly TimeSpan _window; // ex: 30 dias
private readonly Queue<(DateTime ts, bool success)> _events = new();
private readonly object _lock = new();
public SloTracker(string sloName, double target, TimeSpan window)
{
_sloName = sloName;
_target = target;
_window = window;
}
public void Record(bool success)
{
var now = DateTime.UtcNow;
lock (_lock)
{
_events.Enqueue((now, success));
// remover eventos fora da janela
while (_events.TryPeek(out var old) &&
now - old.ts > _window)
_events.Dequeue();
}
}
public SloStatus GetStatus()
{
lock (_lock)
{
if (_events.Count == 0) return new SloStatus(1.0, 0, 0);
int total = _events.Count;
int good = _events.Count(e => e.success);
double sli = (double)good / total;
double budget = _target - sli;
double budgetRemaining = sli - _target + (1 - _target);
return new SloStatus(sli, budget, budgetRemaining / (1 - _target));
}
}
}
public record SloStatus(double Sli, double BudgetConsumed, double BudgetRemainingPct);
Em .NET 10, use System.Collections.Generic.Queue com lock ou um Channel para produção. Para janelas deslizantes de alta performance, considere um ring buffer de tamanho fixo.
from collections import deque
from dataclasses import dataclass
from datetime import datetime, timedelta, UTC
from threading import Lock
@dataclass
class SloStatus:
sli: float
budget_remaining_pct: float
is_burning: bool
class SloTracker:
def __init__(self, name: str, target: float, window: timedelta):
self.name = name
self.target = target # ex: 0.999
self.window = window
self._events: deque[tuple[datetime, bool]] = deque()
self._lock = Lock()
def record(self, success: bool) -> None:
now = datetime.now(UTC)
with self._lock:
self._events.append((now, success))
# remover eventos fora da janela
cutoff = now - self.window
while self._events and self._events[0][0] < cutoff:
self._events.popleft()
def status(self) -> SloStatus:
with self._lock:
if not self._events:
return SloStatus(1.0, 1.0, False)
total = len(self._events)
good = sum(1 for _, ok in self._events if ok)
sli = good / total
error_budget = 1 - self.target # ex: 0.001
consumed = max(0, self.target - sli)
remaining_pct = 1 - (consumed / error_budget) if error_budget else 1.0
return SloStatus(sli, remaining_pct, remaining_pct < 0.5)
Use deque (O(1) para append/popleft) em vez de lista. Em contexto async, troque threading.Lock por asyncio.Lock.
type event struct {
ts time.Time
success bool
}
type SLOTracker struct {
name string
target float64
window time.Duration
mu sync.Mutex
events []event
head int
size int
cap int
}
func NewSLOTracker(name string, target float64, window time.Duration, cap int) *SLOTracker {
return &SLOTracker{
name: name, target: target,
window: window, cap: cap,
events: make([]event, cap),
}
}
func (t *SLOTracker) Record(success bool) {
t.mu.Lock()
defer t.mu.Unlock()
idx := (t.head + t.size) % t.cap
t.events[idx] = event{time.Now(), success}
if t.size < t.cap {
t.size++
} else {
t.head = (t.head + 1) % t.cap
}
}
func (t *SLOTracker) Status() (sli, budgetRemaining float64) {
t.mu.Lock()
defer t.mu.Unlock()
cutoff := time.Now().Add(-t.window)
total, good := 0, 0
for i := 0; i < t.size; i++ {
e := t.events[(t.head+i)%t.cap]
if e.ts.After(cutoff) {
total++
if e.success { good++ }
}
}
if total == 0 { return 1.0, 1.0 }
sli = float64(good) / float64(total)
budget := 1 - t.target
consumed := math.Max(0, t.target-sli)
budgetRemaining = 1 - consumed/budget
return sli, budgetRemaining
}
Ring buffer evita alocações contínuas. Para escalas maiores, use Prometheus histogram_quantile em vez de tracker in-memory — mais resiliente e integrável com alertas.
Erros comuns ao implementar SLOs
O primeiro erro é medir apenas o caminho feliz. Um SLI de "99.9% das requisições retornam 200" ignora latência. Uma API que retorna 200 em 10 segundos está "disponível" segundo esse SLI, mas o usuário certamente não percebe assim. SLI de disponibilidade e SLI de latência devem coexistir.
O segundo erro é não separar SLIs por criticidade de serviço. Um endpoint de relatórios gerenciais que processa em background tem SLO radicalmente diferente de um endpoint de checkout. Juntar tudo em um SLI único "dilui" os problemas: 99.9% global pode esconder que o checkout está a 99.5% e os relatórios estão a 99.99%.
O terceiro erro é definir SLOs sem instrumentação. Times que definem SLOs antes de ter os SLIs medidos estão chutando — e geralmente chutam muito conservadoramente ou imposssivelmente. A sequência correta: instrumentar (2 semanas), medir baseline (4 semanas), definir SLO com margem de ambição, revisar no trimestre seguinte.
SLOs definidos por marketing ou por pressão de vendas sem validação técnica são um dos geradores mais prolíficos de burnout em equipes de engenharia. Um SLA de 99.99% vendido ao cliente quando a arquitetura suporta 99.9% com esforço razoável cria um regime de medo permanente — cada deploy vira ansiedade, cada incidente vira crise existencial. Defenda tecnicamente SLOs realistas antes de assinar contratos com clientes.
SLOs como ferramenta de conversa
Além de sua função técnica, SLOs têm uma função organizacional poderosa: transformam conversas vagas sobre qualidade em conversas quantificáveis sobre custo-benefício. "Devemos investir em melhorar a disponibilidade do checkout?" é uma pergunta difícil sem dados. "O checkout está a 99.85%, abaixo do SLO de 99.9%, e violamos o SLO em 3 das últimas 4 semanas — cada violação de semana representa aproximadamente R$200K em pedidos não convertidos" é uma proposta de investimento.
O próximo conceito, Error Budgets, expande exatamente essa função organizacional do SLO: como o budget derivado do SLO se torna o mecanismo de decisão sobre quando o time pode arriscar mudanças versus quando precisa pausar e estabilizar.
Como praticar
- Instrumentar e calibrar. Escolha um serviço que você opera ou conhece bem. Instrumente dois SLIs: um de disponibilidade (fração de requisições não-5xx) e um de latência (fração abaixo de limiar). Observe por duas semanas. Depois, proponha SLOs baseados nos dados — não em "o que seria bom", mas em "o que o sistema realmente entrega hoje com 10% de margem de ambição".
- Calcular o custo da indisponibilidade. Para o serviço acima, calcule: quantos minutos de downtime cada tier de SLO (99%, 99.9%, 99.99%) permite por mês? Se o sistema perder 100% das requisições durante esses minutos, qual é a perda estimada de receita ou de usuários? Isso âncora a conversa de investimento em confiabilidade em custo real.
- Implementar um burn rate alert. Com os SLIs instrumentados, configure dois alertas de burn rate: um fast burn (14.4× por 1 hora) e um slow burn (1× por 6 horas). Observe por um mês quantas vezes cada alerta dispara e se as causas eram tratáveis. Isso calibra sua sensibilidade de alerta.
Referências para aprofundar
- livro Site Reliability Engineering — Beyer, Jones, Petoff, Murphy (O'Reilly, 2016).
- livro The Site Reliability Workbook — Fowler, Murphy, et al. (O'Reilly, 2018).
- artigo SLOs Should Be a Conversation, Not a Contract — Charity Majors (Honeycomb, 2020).
- artigo The Art of SLOs — Google SRE (workshop material, 2018).
- docs AWS Service Level Agreements — Amazon Web Services.
- artigo Alerting on SLOs like Pros — Björn Rabenstein (2019).
- livro Implementing Service Level Objectives — Alex Hidalgo (O'Reilly, 2020).
- vídeo The Mathematics of SLOs — Dave Rensin (SREcon Americas, 2019).
- artigo SLO Burn Rate Alerts in Prometheus — Google Cloud (2022).
- paper Latency-based SLOs for Real-Time Systems — Dean & Barroso (CACM, 2013).
- docs OpenTelemetry Metrics Specification — CNCF.
- artigo How Spotify Defines SLOs — Engineering Blog, 2021.