Documentação de plataforma tende a descrever cada produto em isolamento, no melhor ângulo possível. Isso cria uma leitura onde Workers parece mais poderoso que Pages e Pages parece mais simples que Workers. Nenhuma das duas leituras é correta. Eles têm capacidades genuinamente exclusivas em cada direção — e uma zona de sobreposição ampla onde a diferença é apenas de modelo de deploy.
O que só Workers tem
Cron triggers são o primitivo mais relevante que não existe em Pages. No wrangler.toml:
[triggers] crons = ["0 3 * * *", "*/15 * * * *"]
Isso registra dois crons: um às 3h da manhã todos os dias, outro a cada 15 minutos. O handler correspondente é o método scheduled do objeto exportado pelo Worker. Pages não tem essa primitiva. Não é limitação de runtime — é uma decisão de produto. Se você precisa de execução periódica, é um Worker autônomo.
Queues consumers operam de forma análoga. O Cloudflare Queues permite enfileirar mensagens e processá-las de forma assíncrona. O consumer — o Worker que lê da fila — é configurado no wrangler.toml com [[queues.consumers]]. Pages Functions não podem ser consumers de fila; só podem publicar mensagens em filas via binding.
Email Workers recebem e-mails diretamente. Você configura uma rota de e-mail na Cloudflare para apontar para um Worker, e o Worker recebe o e-mail como um objeto com remetente, destinatário, cabeçalhos e corpo. Isso permite processar bounces, parsear recibos de nota fiscal, ou rotear e-mails para diferentes filas — tudo sem servidor de e-mail próprio. Pages não suporta esse trigger.
Workers for Platforms é o mecanismo de multi-tenancy onde usuários de um SaaS podem fazer deploy dos próprios Workers dentro da conta do operador. O operador usa um Worker de dispatch que recebe requisições e as encaminha para o script do tenant correto. É uma primitiva de infraestrutura para plataformas que precisam executar código arbitrário de usuários com isolamento garantido. Exclusivo de Workers.
TCP Sockets (em beta) permitem conexões TCP diretas de um Worker — útil para conectar a bancos de dados que não têm API HTTP, como PostgreSQL ou Redis sem Upstash. Ainda em evolução, mas sem equivalente em Pages.
Durable Object Alarms merecem menção separada dos Durable Objects em geral. Os DOs funcionam nos dois, mas os alarms — timers que acordam um DO específico em um horário definido — são uma primitiva de agendamento que complementa os cron triggers para casos com estado por entidade (agendar um lembrete por usuário, por exemplo). Disponível nos dois runtimes, mas a orquestração normalmente parte de um Worker com trigger de cron ou de fila.
O que só Pages tem
Hospedagem de assets estáticos com custo zero por requisição é a capacidade mais subestimada de Pages e a mais cara de replicar fora dela. Quando você faz deploy de um projeto Pages, os arquivos estáticos (HTML, CSS, JavaScript, imagens, fontes) são distribuídos pelo CDN global da Cloudflare. Requisições para esses assets não passam pelo runtime de Workers — são servidas diretamente da borda do CDN, sem acionar nenhuma lógica de computação, sem contar como invocação, sem custo por requisição além do plano de Pages.
O plano gratuito de Pages inclui requests CDN ilimitados. O plano pago custa $20/mês e adiciona 5.000 builds/mês e até 5 builds concorrentes. Para um site com decenas de milhões de pageviews mensais, essa ausência de custo por requisição estática é uma vantagem de billing significativa sobre qualquer arquitetura baseada em Workers puros.
Preview deployments automáticos por branch são o segundo diferencial. Cada push para uma branch não-principal gera uma URL única no formato hash-branch.seuprojeto.pages.dev, com assets e Functions rodando juntos. Nenhuma configuração adicional, nenhum script de CI para escrever. Workers não replica isso nativamente — você precisa montar o fluxo de "deploy de branch" manualmente no seu CI.
O pipeline de build integrado também é exclusivo. Pages detecta o framework (Next.js, Astro, SvelteKit, Nuxt, Hugo, Gatsby), configura os defaults de build, e executa o processo de build em ambiente isolado a cada push. Para Workers, o build é responsabilidade do seu CI — o que é mais flexível, mas significa mais configuração para manter.
As convenções _redirects e _headers permitem configurar redirecionamentos e cabeçalhos HTTP para assets estáticos via arquivos de texto simples na raiz do projeto, sem código. Útil para migrações de URL, HSTS, Content Security Policy e headers de cache. Workers podem implementar o mesmo com código, mas é mais verboso.
O que os dois têm em comum
O runtime V8 é idêntico. Os limites são os mesmos: 128MB de memória (hard), 10MB de script comprimido no plano pago, 30s de CPU por requisição, 1.000 subrequests por invocação. Qualquer código que roda em Workers roda em Pages Functions sem alteração.
Os bindings de dados são compartilhados: D1 (SQLite no edge), KV (chave-valor distribuído), R2 (armazenamento de objetos), Durable Objects (estado consistente com coordenação), AI (inferência de modelos no edge). Você pode ter um banco D1 acessado tanto por Pages Functions quanto por um Worker autônomo configurado no mesmo wrangler.toml com o binding apontando para o mesmo database ID.
Service Bindings funcionam nos dois: uma Pages Function pode chamar um Worker autônomo diretamente via binding interno, sem latência de rede pública. Um Worker pode chamar outro Worker. A chamada é uma fetch() normal contra o binding, mas roteada internamente na rede da Cloudflare.
A arquitetura que usa cada um no lugar certo
O padrão que emerge de projetos que usam Workers e Pages corretamente tem três camadas. A primeira é o projeto Pages: serve o SPA ou site gerado por build, com assets estáticos no CDN sem custo por requisição. As rotas de API ficam em /functions/api/ — Pages Functions co-localizadas com o frontend, com preview por branch incluído, acessando D1 e KV para os dados da aplicação.
A segunda camada são Workers de jobs assíncronos: scripts autônomos com cron triggers para processamento agendado, consumers de Queues para trabalho assíncrono desacoplado do caminho crítico HTTP, Email Workers para processamento de e-mail. Esses Workers acessam os mesmos bindings de dados do projeto Pages — o mesmo banco D1, o mesmo KV namespace.
A terceira camada é a comunicação entre elas via Service Bindings. Uma Pages Function que precisa de processamento pesado chama o Worker especializado diretamente, sem HTTP externo. O Worker de cron que precisa disparar uma notificação pode chamar a Pages Function de envio via Service Binding.
Essa arquitetura não é teórica. É o que acontece quando você usa cada primitivo onde ele resolve o problema com menor custo operacional: CDN gratuito do Pages para assets, mesmo runtime para a API co-localizada, Workers autônomos para os triggers que Pages não suporta.
O mapa de decisão
A pergunta que organiza a decisão é: o que dispara esse código? Se é uma requisição HTTP e o código mora junto com um frontend, Pages Functions. Se é uma requisição HTTP mas o projeto não tem frontend — serviço de API puro — Workers com configuração em wrangler.toml. Se é qualquer coisa diferente de HTTP — horário agendado, mensagem de fila, e-mail recebido — Workers sem alternativa.
Os dois lados da mesa têm capacidades que o outro não replica sem custo ou complexidade adicional. A decisão que ignora isso — usar só Workers por achar mais "sério", ou só Pages por achar mais simples — vai bater num limite que obriga refatoração mais cedo do que o necessário.
Leia também
- Cloudflare Workers vs Pages: a diferença que importa antes de você escolher
- Migrar de Pages para Workers: quando faz sentido e o custo real da mudança
- Workers e Pages: deploy, roteamento e o que cada modelo esconde
- Pages Functions: quando usar em vez de Workers puros
- KV para rate limiting, feature flags e configuração distribuída: onde funciona e onde quebra
- Cloudflare KV: o que globalmente distribuído significa quando você precisa escrever