O custo oculto da orquestração com estado
SchemaBridge Team · 2026-02-02 · Distributed Systems, Immutable Infrastructure, Orchestration, Anti-Patterns, Reliability
Por que suas ferramentas internas "simples" podem ser seu maior risco de confiabilidade e como aplicar padrões de infraestrutura imutável à lógica de aplicação pode salvar você.
No mundo dos microsserviços, somos obcecados por desacoplamento. Usamos filas, adotamos arquiteturas orientadas a eventos e quebramos monólitos. Ainda assim, dentro dos nossos motores de orquestração, muitas vezes cometemos o pecado capital dos sistemas distribuídos: escrevemos loops com estado.
Na SchemaBridge, reformulamos recentemente nossos workflows de sistema centrais — aqueles que conduzem nossos próprios rollouts graduais. Ao fazer isso, nos deparamos com os mesmos antipadrões que afligem muitas organizações de engenharia. Esta não é apenas uma história sobre nossas notas de versão; é um exercício de aplicação dos princípios de infraestrutura imutável à camada de aplicação.
O antipadrão do "loop"
Considere o clássico "poller":
while not deployment.is_ready():
sleep(60)
check_status()
Esse código pressupõe um universo estável. Pressupõe que o processo de polling viverá para sempre. Na realidade, isso é um artefato de monólito distribuído. Um processo que mantém seu estado em memória durante uma longa espera síncrona é frágil: quando o host reinicia ou uma chamada trava, ele perde esse estado ou fica para trás como um "zumbi" que ninguém observa, e seus modos de falha se tornam imprevisíveis.
A solução: encadeamento recursivo
Passamos de um loop while interno para um modelo de execução recursivo, semelhante ao Continuation Passing Style usado em programação funcional.
- Padrão: Cada rodada dispara um workflow filho de monitoramento que espera com uma etapa
DELAYdurável em vez desleep(); em seguida, uma etapaSPAWNERinicia a próxima rodada como um workflow filho — o workflow de rollout dispara outra execução de si mesmo. - Resultado: O pai continua esperando que o filho dê retorno, mas espera de forma durável: a espera é uma linha no PostgreSQL (um merge
WAIT_ALLaguardando o callback do filho), não uma thread nem um loop em memória. Se um worker morrer no meio do rollout, nada se perde; o estado do banco de dados continua sendo a fonte da verdade.
Lógica imutável: versionamento com hashing canônico
Versionamento é notoriamente difícil. Quando você atualiza a definição de um workflow, o que acontece com as execuções que já estão rodando?
- O antipadrão: "Atualizações in-place". Você faz o deploy de código novo e as execuções existentes de repente passam a se comportar de outro jeito.
- O padrão do setor: Infraestrutura imutável. Assim como não entramos via SSH nos servidores para aplicar patches (nós os substituímos), não deveríamos aplicar patches em definições de workflow em execução.
As versões de workflow na SchemaBridge são imutáveis: um deploy cria uma nova versão, e uma execução fica vinculada à versão em que começou. O que adicionamos foi o hashing canônico da DSL: toda definição de workflow importada é serializada em uma forma JSON canônica e passa por hash, e o hash é armazenado com o workflow (dslHash).
Esse hash responde a uma pergunta que costumava ser surpreendentemente difícil — a lógica realmente mudou? Quando uma importação de configuração ou o nosso próprio bootstrap de workflows de sistema encontra uma definição cujo hash coincide com o que já está em produção, ele planeja um no-op em vez de refazer o deploy, e um workflow em produção que se desviou da sua definição de origem pode ser detectado comparando hashes.
Trancando o "modo deus"
Por fim, tratamos da segurança das ferramentas internas. É comum dar acesso root a scripts internos de "limpeza". Isso viola o princípio do menor privilégio.
Descobrimos que nossa própria ferramenta interna de "Gradual Rollout" localizava os workflows sobre os quais operava por meio de IDs lógicos fixos no código, o que facilitava apontá-la para o workflow errado — e sobrescrevê-lo. Corrigimos isso de duas formas:
- Resolver por papel, não por nome: O rollout agora encontra seu ponto de entrada de destino por meio de tags explícitas, validadas quanto à unicidade, em vez de buscas por IDs lógicos fixos no código.
- Uma credencial de menor privilégio: As etapas Gateway dos nossos workflows de rollout se autenticam com sua própria API key nomeada, que propositalmente não tem
config:manage— a permissão para reescrever a configuração do tenant de sistema. A automação que roda a partir do lugar menos confiável não consegue mais alterar as regras sob as quais roda.
Conclusão
Se a sua orquestração depende de sleep(), você está lutando contra a nuvem.
Ao adotar recursão, imutabilidade e menor privilégio, passamos de uma orquestração "baseada em esperança" para uma orquestração cujo estado você consegue inspecionar e cujo raio de impacto você consegue limitar.
Leitura complementar: