Pular para o conteúdo

ADR 0001 — Runtime em Cloudflare Workers com núcleo funcional

Status: canônico · Escopo: Runtime de execução, composição de dependências, filas e estado do apps/api-worker · Atualizado em: 2026-07-28

Registra por que o runtime roda em Cloudflare Workers com hexagonal e injeção de dependência funcional, e por que NestJS, BullMQ e Redis foram descartados. Existe porque essa pergunta já voltou mais de uma vez.

O produto atende telefone: uma ligação chega, o agente precisa responder em menos de um segundo, e o tráfego é irregular — zero por horas, picos em emergência. Precisávamos decidir três coisas juntas: onde o código roda, como as dependências são compostas, e onde vive estado com temporizador.

A dúvida foi levantada explicitamente: um ecossistema Node maduro (NestJS para estrutura, BullMQ para filas, Redis para estado efêmero) é o caminho mais batido e tem mais gente no mercado que já conhece.

O runtime é Cloudflare Workers. A arquitetura é hexagonal / ports-and-adapters com núcleo funcional: casos de uso declaram uma interface do que precisam e recebem um argumento deps; os repositórios concretos vêm de fábricas createXxxRepo(sql); a montagem acontece nos pontos de entrada (Durable Object, consumidores de fila, handlers HTTP). Sem framework de injeção de dependência.

Estado com temporizador vive em Durable Objects; enfileiramento em Cloudflare Queues; persistência em Neon Postgres.

Fica mais fácil: latência baixa na borda sem servidor para manter; cada caso de uso é testável com deps mockado, sem container de DI nem bootstrap de framework; serialização por conversa sai de graça no Durable Object; custo acompanha o tráfego irregular.

Fica mais difícil: não há decorators nem descoberta automática — a montagem é explícita e cresce nos pontos de entrada (por isso a regra de extrair um builder quando o mesmo conjunto de repositórios aparece em dois lugares). Bibliotecas que assumem APIs de Node longevo não servem. O modelo mental de V8 isolates é menos familiar que um servidor Node.

Passa a ser proibido: dependência que exija processo Node de vida longa, servidor com estado em memória entre requisições, ou framework que precise de container de DI em tempo de execução.

AlternativaPor que perdeu
NestJSTecnologia de servidor Node: container de DI em runtime, decorators e ciclo de vida de módulos pressupõem processo longevo. Incompatível com V8 isolates. O que ele resolveria — estrutura e testabilidade — já é resolvido por interfaces deps explícitas, com menos indireção.
BullMQDepende de Redis e de workers Node persistentes. Cloudflare Queues cobre enfileiramento, retry e DLQ dentro do mesmo runtime, sem infraestrutura extra.
RedisFoi considerado para working memory e estado efêmero. Durable Objects já dão serialização por conversa e alarmes, e Postgres já é a fonte de verdade — um terceiro armazenamento adicionaria operação e um caminho de inconsistência sem resolver nada novo.