MÓDULO 08 · CONCEITO 01 DE 14

SLI, SLO e SLA

Definindo disponibilidade com precisão — do indicador ao contrato

Tempo de leitura ~22 min Pré-requisito Módulo 07 — Escalabilidade Próximo 02 · Error budgets

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.

heurística do sênior

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.

armadilha clássica

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.

princípio orientador

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.

C# — SLO tracker com sliding window
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.

Python — SLO tracker com deque
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.

Go — SLO tracker com ring buffer
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.

armadilha em produção

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

  1. 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".
  2. 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.
  3. 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

  1. livro Site Reliability Engineering — Beyer, Jones, Petoff, Murphy (O'Reilly, 2016). Capítulos 4 e 5 são a fonte primária do framework SLI/SLO/SLA. Leitura obrigatória — disponível gratuitamente em sre.google/sre-book.
  2. livro The Site Reliability Workbook — Fowler, Murphy, et al. (O'Reilly, 2018). Aprofunda o capítulo prático de SLOs com exemplos reais. Burn rate alerts em detalhes. Disponível em sre.google/workbook.
  3. artigo SLOs Should Be a Conversation, Not a Contract — Charity Majors (Honeycomb, 2020). Argumento poderoso sobre por que SLOs sem cultura de engajamento viram burocracia. Complementa o lado humano que o SRE Book não cobre.
  4. artigo The Art of SLOs — Google SRE (workshop material, 2018). sre.google/resources/practices-and-processes/art-of-slos. Workshop de 3 horas sobre como definir SLOs em equipe — material prático excelente.
  5. docs AWS Service Level Agreements — Amazon Web Services. aws.amazon.com/legal/service-level-agreements. Bons exemplos de como SLAs reais são escritos em contexto comercial. Útil para entender o que prometer ao cliente.
  6. artigo Alerting on SLOs like Pros — Björn Rabenstein (2019). Aprofundamento em burn rate alerting, com fórmulas e exemplos de configuração em Prometheus. Base matemática para os alertas de queima rápida/lenta.
  7. livro Implementing Service Level Objectives — Alex Hidalgo (O'Reilly, 2020). Livro dedicado inteiramente a SLOs na prática — mais pragmático que o SRE Book. Cobre implementação em equipes de todos os tamanhos.
  8. vídeo The Mathematics of SLOs — Dave Rensin (SREcon Americas, 2019). YouTube. Apresentação rigorosa sobre como calcular SLOs, janelas, e burn rate. 45 minutos bem investidos para quem quer entender o lado matemático.
  9. artigo SLO Burn Rate Alerts in Prometheus — Google Cloud (2022). cloud.google.com/stackdriver/docs/alerting/slo-alerts. Tutorial prático de implementação de alertas de burn rate em Prometheus/Grafana.
  10. paper Latency-based SLOs for Real-Time Systems — Dean & Barroso (CACM, 2013). "The Tail at Scale". Fundamenta por que usar percentis (P99, P999) em vez de médias para SLIs de latência. Referência canônica.
  11. docs OpenTelemetry Metrics Specification — CNCF. opentelemetry.io/docs/specs/otel/metrics. Base técnica para instrumentar SLIs de forma portável e padronizada.
  12. artigo How Spotify Defines SLOs — Engineering Blog, 2021. engineering.atspotify.com. Caso real de adoção de SLOs em escala — incluindo as partes que não funcionaram. Leitura honesta.