Sistemas distribuídos têm bugs que testes nunca pegam. Race conditions em cenários raros, perda de evento em network partition específica, livelock de retry, violações de invariants num caminho que ninguém pensou em testar. Quando AWS cita TLA+ em 04-03, DynamoDB, EBS; quando MongoDB, Cosmos DB, Tendermint, Tezos publicam specs em TLA+/Coq/Isabelle, não é academia. É a única ferramenta confiável pra provar propriedades sobre design distribuído antes de escrever código.
Formal methods não substituem testes nem code review. Substituem whiteboard sessions vagas ("acho que essa fila funciona") por modelos executáveis que o computador checa exaustivamente. Você desenha o sistema, escreve invariants ("todo pedido finalizado tem pagamento confirmado"), e o model checker explora todos os interleavings possíveis dentro do bound, finds counterexamples impossíveis de encontrar manualmente.
Senior de sistemas sérios deve saber escrever TLA+ pra problemas críticos: protocolo de consensus custom, fila de outbox com retries, reconciliation de pagamento, escalonador de jobs. Não vai usar todo dia, mas vai usar quando o custo de bug é alto.
Este módulo é formal methods aplicado: TLA+ + TLC, PlusCal, P language (Microsoft), Alloy. Specifications, invariants, temporal properties, refinement, e quando NÃO usar (cost > benefit em código simples).
2. Teoria Hard
2.1 Por que formal methods
Testes mostram presença de bugs, não ausência. Em sistema distribuído com N processos e mensagens out-of-order, número de interleavings cresce combinatorialmente. Testes hit menos de 0.0001% deles.
Model checking explora todos os states alcançáveis (até bound). Encontra contraexemplo se invariant viola.
Ganho real: especificar é onde você descobre o bug. 80% dos benefícios vêm de escrever a spec (forças clarity), 20% de rodar TLC.
2.2 TLA+ overview
TLA+ (Temporal Logic of Actions, Lamport): linguagem de especificação formal. Componentes:
Variables: estado.
Init: predicado inicial.
Next: predicado de transição (relação entre estado atual e próximo).
Specification high-level (abstract) → low-level (mais detalhada). Refinement: low-level implementa high-level (toda execução de low é também execução de high).
Útil pra conectar spec abstrata ("consensus") com algoritmo concreto (Paxos).
2.7 P language (Microsoft), deep
P (Microsoft Research, 2013+) é linguagem state-machine first pra modelagem de sistemas event-driven assíncronos. Diferente de TLA+ (specification language puro), P é executável: você escreve spec e gera código de teste pra implementação real.
Modelo conceitual:
Cada componente é uma state machine com handlers de mensagem.
Componentes comunicam via messaging assíncrono (semantics actor-like).
Modular checker explora todas interleavings de mensagens dentro de bound.
Tem simulation mode + stress testing + systematic exploration.
Exemplo conceitual:
machine Replica {
start state Init {
on PrepareReq do (req: PrepareReq) {
// logic
send req.from, PrepareAck;
goto Active;
}
}
state Active { ... }
}
Generates test harness: state machines viram testes unitários executáveis em C# (ou em runtimes que P alvo).
Microsoft uso real: Service Fabric, Azure Storage. Bug-find em prod publicado.
Vs TLA+:
TLA+: matemática elegante, melhor pra invariants e temporal logic abstrato.
P: imperativo, código-like. Time de devs aceita mais fácil.
TLA+: spec só. P: spec + executável + test harness.
TLA+ tem comunidade maior, mais resources educacionais (Hillel Wayne).
P é mais novo, comunidade menor. Cresceu post-2020.
2.8 Alloy, deep
Alloy (MIT, Daniel Jackson): structural specification language. Você define objects + relations, declara invariants e operations, e Alloy Analyzer (Kodkod backend) busca contraexemplo via SAT solver dentro de bound finito ("small scope hypothesis": bugs aparecem em modelos pequenos se aparecem).
Exemplo conceitual:
sig User { friends: set User }
fact NoSelfFriend { all u: User | u not in u.friends }
fact Symmetric { friends = ~friends }
pred AddFriend [u, v: User, u', v': User] {
u'.friends = u.friends + v
v'.friends = v.friends + u
}
assert NoSelfAfterAdd { all u, v, u', v' | AddFriend[u,v,u',v'] => u not in u'.friends }
check NoSelfAfterAdd for 5
alloy
Onde Alloy brilha:
Schema design: modelar invariants em árvores, grafos, schemas relacionais.
Data structure invariants: red-black tree properties, B-tree balancing.
Specification de protocolo de simples a médio.
Trade-offs:
Bound finito: não prova pra todos os tamanhos. Confidence é "checked up to N".
Não tem temporal logic forte como TLA+. Versão Electrum/Alloy 6 adicionou temporal mas TLA+ ainda mais maduro.
Ferramenta IDE (Alloy Analyzer) é bom mas dated.
Quando escolher: modelagem de structures/data invariants > distributed protocols. Pra distributed, TLA+ ou P são primeira escolha.
2.9 Coq, Isabelle, Lean: theorem provers, deep
Diferente de model checking. Theorem prover ajuda a escrever prova de teorema; sistema valida cada passo. Não busca contraexemplo automaticamente, você guia a prova.
Coq: clássico. Prova interativa em Gallina. CompCert (compilador C verificado), Software Foundations (curso), CertiKOS (microkernel).
Isabelle/HOL: mais popular em ambientes acadêmicos europeus. seL4 microkernel formalmente verificado. Mathlib alternativa em Lean.
Lean 4 (Microsoft Research, emergente em 2023+):
Linguagem dual: pode ser usado como linguagem de programação e prover. Muito relevante em 2026.
mathlib4: maior biblioteca de matemática formalizada do mundo (~1M+ lines), liderada por Kevin Buzzard. Cresceu rápido em 2024-2025.
Performance: Lean 4 compila pra C, performance comparable a OCaml. Outros provers são interpretativos.
Tactic language moderno (Mathlib.Tactic) reduz boilerplate vs Coq.
Adoção crescente em sistemas reais: Amazon (Cedar policy language verificada em Lean 4), Stripe (alguns componentes).
Onde theorem provers agregam (em sistemas, não academic):
Compilers (CompCert, CakeML).
Microkernels (seL4, CertiKOS).
Cryptographic primitives (HACL*, fiat-crypto).
Smart contracts (alguns DeFi protocols têm specs em Coq).
Security policies (Amazon Cedar via Lean 4).
Consensus protocols (Tendermint, Cosmos partes).
Cost altíssimo: semanas/meses por theorem em sistemas reais. Reservado a:
Crítica de vida (avionics, medical devices).
Cryptography (correctness é pré-requisito).
Componente de OS / kernel onde bug = root.
Smart contracts $$$ que viraram targets de attack.
Em 2026 vale acompanhar Lean 4: ferramenta que pode democratizar parte do espaço. Já há tutoriais "Lean for Engineers" emergindo.
2.10 Onde formal methods agregam
AWS publicou: TLA+ em DynamoDB, 04-03, EBS, Aurora. "Found subtle bugs that would have taken months in production." MongoDB usa em replica set protocol. Tendermint, Cosmos, Ethereum 2.0 spec em K, Coq, Lean.
Patterns onde se justifica:
Consensus protocols (Raft, Paxos variantes).
Coordination (locks distribuídos, leases).
Reconciliation (idempotent batch jobs).
State machines críticas (payment, inventory).
Migration de schema (downtime zero).
Rate limiting / token bucket sob retries.
2.11 Quando NÃO usar
Código sequencial simples: tests batem.
Time não tem buy-in: spec abandonada após primeiro draft.
Problema mal definido: spec espelha confusão.
ROI: se bug custa > 1 mês em produção, vale formal. CRUD app, raramente.
2.12 Exemplo: outbox pattern em TLA+
Outbox: write transaction insere row em outbox; worker lê e publica. Invariants:
Toda row publicada existe na tabela source.
Toda row source eventualmente publicada (se worker live).
Não há publish duplicado (effective-once).
Modelar: states = outbox table + published log + worker state. Actions = insert (write txn), pick (worker reads), publish (worker emits to broker), ack (commit position). Invariant Consistent checa.
TLC explora interleaving worker crash mid-publish → worker restart → re-emit. Detecta se invariant breaks. Você corrige protocol se sim.
2.13 Workflow de formal methods
Define problem: que invariants importam.
Spec abstrata: minimal model das ações e estado.
Roda TLC em modelo pequeno; corrige até passar.
Aumenta modelo: mais processos / mensagens.
Refinement: spec mais detalhada se precisa.
Implementa código alinhado com spec.
Teste: integration tests confirmam empiricamente.
2.14 PlusCal patterns úteis
Atomic actions: cada labeled step.
Process types: process (W \in Workers).
Channels: variables + actions de send/receive.
Failures: process termina ou crashes (modelo de unreliable).