Como Parar de Corrigir Sistemas Distribuídos e Começar a Viver com Restate
Imagine o seguinte: você está escrevendo um microsserviço para processamento de pagamentos. No meio do processo, a rede falha, o banco de dados dá timeout, ou o container simplesmente reinicia. O que acontece com a transação? No cenário clássico, você precisa implementar manualmente lógica de retry, rastrear idempotência, configurar filas de mensagens e, muito provavelmente, introduzir algum saga complexo. É doloroso, consome tempo e transforma seu código em um labirinto de handlers de erro.
Recentemente descobri o Restate, um projeto que ataca esse problema no nível da infraestrutura. Os desenvolvedores chamam de "Execução Durável" — execução de código tolerante a falhas. A ideia é que seu código se torna imortal: se um processo trava, o Restate o retoma exatamente de onde parou, preservando todas as variáveis e estado.
O que exatamente é isso
Restate é um binário em Rust que funciona como um servidor proxy e coordenador para seus serviços. Ele assume todo o trabalho pesado de gerenciamento de estado e chamadas. Você escreve código comum em TypeScript, Python ou Go, usa o SDK e, de repente, suas funções se transformam em workflows confiáveis.
A principal diferença para soluções mais pesadas como o Temporal é que o Restate é muito mais fácil de começar. Você não precisa de uma configuração massiva de bancos de dados e workers complexos. Você pode simplesmente rodar um único binário ou container Docker e começar a trabalhar.
Como o Restate ajuda na prática
O projeto inclui vários conceitos interessantes que realmente simplificam sua vida.
Execução garantida
Se você chamou uma função através do Restate, ela vai executar até o final. Ponto final. Se o servidor que executa seu código trava, o Restate espera ele voltar e continua a execução a partir do último passo bem-sucedido. Você não precisa mais se preocupar se o e-mail foi enviado duas vezes para o usuário ou se o dinheiro foi cobrado duas vezes.
Timers e promises inteligentes
Normalmente, implementar um delay em um sistema distribuído é uma jornada. Você precisa colocar uma mensagem em uma fila de delay ou configurar um cron job. No Restate, você simplesmente escreve ctx.sleep(duration). A thread não bloqueia inutilmente: o serviço pode ser desligado completamente, e três dias depois o Restate vai "acordá-lo" e continuar a execução.
Estado direto no código
O Restate permite armazenar estado K/V vinculado a uma entidade específica (por exemplo, um ID de usuário). Parece trabalho normal com objetos, mas por baixo dos panos o Restate garante que os dados são consistentes e sempre disponíveis junto com a requisição. Isso é especialmente conveniente para arquiteturas serverless onde funções tipicamente não têm memória.
Como fica no código
Digamos que precisamos implementar um processo de registro de usuário com confirmação por e-mail. Em TypeScript usando o SDK do Restate, ficaria algo assim:
import * as restate from "@restatedev/restate-sdk";
const userService = restate.service({
name: "users",
handlers: {
register: async (ctx: restate.Context, user: { id: string, email: string }) => {
// Сохраняем состояние
ctx.set("status", "pending");
// Отправляем письмо (Restate гарантирует, что это случится 1 раз)
await ctx.run(() => sendWelcomeEmail(user.email));
// Ждем подтверждения или таймаута в 24 часа
const confirmed = await ctx.awakeable<boolean>("email-confirmed");
if (confirmed) {
ctx.set("status", "active");
}
}
}
});
Aqui ctx.run garante que o efeito colateral (enviar o e-mail) vai executar com sucesso, e o resultado será cacheado. Se a função travar depois de enviar, ao reiniciar o Restate simplesmente pula esse passo, sabendo que já foi feito.
O lado técnico
O projeto é escrito em Rust, o que oferece excelente performance. Arquiteturalmente, o Restate atua como um invocador. Ele recebe requisições entrantes via HTTP/gRPC, escreve no seu log e chama seus handlers.
Curiosamente, o Restate pode "suspender" a execução. Se seu código está esperando uma resposta de uma API externa ou um timer, o Restate libera os recursos. Quando o evento ocorre, ele restaura o contexto de execução. Isso permite rodar milhares de processos de longa duração em hardware modesto.
Quem deveria experimentar
O Restate vai preencher perfeitamente lacunas em projetos onde:
- Existem muitas cadeias de chamadas entre microsserviços.
- Você precisa construir cadeias complexas de ações (sagas, workflows).
- Você está usando agentes de IA que precisam esperar muito tempo por respostas de LLMs e preservar o contexto da conversa.
- Existem tarefas de execução adiada (lembrete de carrinho abandonado em 2 horas).
O projeto está em desenvolvimento ativo, com quase 4.000 estrelas no GitHub. SDKs estão disponíveis para TypeScript/JavaScript, Java/Kotlin, Python, Go e Rust.
Claro, você não deveria se apressar para colocar um novo componente de infraestrutura na produção de um grande banco amanhã — primeiro, você precisa testar localmente. Mas para startups ou novas funcionalidades em projetos existentes, isso pode economizar semanas de desenvolvimento.
Você pode testar em literalmente alguns minutos:
brew install restatedev/tap/restate-server
restate-server
E pronto, você tem um ambiente local para rodar aplicações tolerantes a falhas. Talvez essa seja a menor barreira de entrada para o mundo da Execução Durável no momento.
Projetos relacionados