Como a migração da Vercel para o Cloudflare Workers + Railway reduziu nossos custos de infraestrutura web em 80%

Migramos nossa stack web da Vercel para o Cloudflare Workers e o Railway, substituindo o Next.js por uma combinação de TanStack Router, TanStack Start e Hono, conforme as necessidades de cada carga de trabalho. O resultado foi uma redução de cerca de 80% nos custos de infraestrutura, chegando a aproximadamente 90% após filtrarmos o tráfego automatizado malicioso na borda da rede. A maior parte do trabalho de migração foi realizada por agentes de IA especializados em programação, enquanto os engenheiros se concentraram na arquitetura, nas restrições, na revisão e na verificação em produção.

23 de setembro de 2026

Quang Lam · Founder & CEO

Como a migração da Vercel para o Cloudflare Workers + Railway reduziu nossos custos de infraestrutura web em 80%

Durante anos, a Vercel foi a plataforma padrão para colocar no ar quase tudo o que fazíamos para a web na WebCatalog. A maioria desses projetos usava Next.js, então a combinação era natural. Nossos sites de marketing, interfaces de produto, configurações de conta, console de desenvolvedores, autenticação, ferramentas administrativas e APIs acabaram todos em praticamente a mesma stack.

Isso funcionou bem por muito tempo. A Vercel simplificava os deploys, o Next.js nos oferecia um framework full-stack produtivo e raramente precisávamos pensar na infraestrutura por trás de qualquer um dos dois.

Com o tempo, essa conveniência deixou de corresponder às necessidades dos nossos produtos.

Nossos sites de marketing ainda se beneficiavam de SSR (renderização no servidor), mas a maioria dos outros aplicativos web não. Eles poderiam ser simples SPAs (aplicativos de página única). Nossas APIs precisavam de um ambiente Node.js convencional, com dependências nativas e processos de longa duração. Quase todo o restante da nossa stack de frontend já usava Vite. Ao mesmo tempo, os custos de infraestrutura estavam ficando mais difíceis de ignorar, especialmente com o crescimento do tráfego público e automatizado.

Inicialmente, tentamos otimizar o que já tínhamos. Consideramos manter o Next.js e levá-lo para o Cloudflare Workers por meio de um adaptador. Experimentamos o Astro nos sites de marketing. Por um breve período, colocamos nossas APIs no Cloudflare Containers.

No fim, chegamos a uma solução mais simples: a maioria dos nossos aplicativos web agora usa Vite + TanStack Router no Cloudflare Workers, nossos sites de marketing usam TanStack Start com SSR no Cloudflare Workers, e nossas APIs usam Hono + tRPC no Railway, em contêineres Node.js de longa duração.

A migração reduziu nossos custos de infraestrutura web em cerca de 80%. Depois que também reforçamos nossas regras de segurança no Cloudflare e passamos a bloquear mais tráfego automatizado hostil na borda da rede, a economia total chegou a aproximadamente 90%.

A maior parte da implementação da migração também foi realizada por agentes de programação com IA, principalmente Claude Fable 5 e Claude Opus 5, enquanto os engenheiros decidiam a arquitetura, definiam as restrições, revisavam as alterações e verificavam o resultado.

Não começamos saindo da Vercel

Nosso primeiro impulso foi otimizar a configuração existente.

O webcatalog.io era o ponto de partida mais óbvio, pois recebe muito tráfego público, embora a maioria de suas páginas mude com relativamente pouca frequência. Descobrimos que uma parte grande demais do site ainda era renderizada dinamicamente. Por isso, corrigimos a renderização dinâmica acidental, adicionamos ISR (regeneração estática incremental) às rotas de alto tráfego, tornamos mais páginas passíveis de cache e otimizamos o processamento custoso dos sitemaps.

Esse trabalho ajudou, mas também deixou o problema de fundo mais claro. Estávamos gastando cada vez mais tempo tentando entender por que conteúdo relativamente estático era tratado como dinâmico, qual comportamento do framework causava isso e qual recurso do framework precisaríamos introduzir para que ele pudesse voltar a ser armazenado em cache.

Enquanto isso, muitos dos nossos outros aplicativos tinham o problema oposto. Configurações de conta, o console de desenvolvedores, aplicativos administrativos e a maioria das interfaces de produto não precisavam de renderização no servidor. Eram aplicativos executados no navegador que se comunicavam com APIs.

Nesse momento, a pergunta deixou de ser “Como reduzimos nossa fatura da Vercel?” e passou a ser “O que construiríamos se esses aplicativos ainda não fossem feitos em Next.js?”

Consideramos usar Next.js no Cloudflare

A opção menos disruptiva era manter o Next.js e transferi-lo da Vercel para o Cloudflare Workers.

Consideramos seriamente essa opção porque o Next.js pode ser executado no Cloudflare por meio de camadas de adaptação, o que nos permitiria preservar boa parte da estrutura dos aplicativos existentes.

Mas não considerávamos o Next.js no Cloudflare equivalente ao Next.js na Vercel. O Next.js tem sua integração mais estreita com o runtime, o sistema de deploy, o comportamento de cache e os recursos de plataforma da Vercel. No Cloudflare, um adaptador precisa traduzir essas premissas para outro runtime.

Isso pode funcionar bem, mas, se o objetivo era simplificar a stack, adicionar mais uma camada de compatibilidade não parecia ideal.

Havia também uma questão mais ampla relacionada às ferramentas. Quase tudo o que estávamos desenvolvendo no frontend já usava Vite: aplicativos desktop, extensões de navegador, SPAs e outros projetos client-side.

O Next.js havia passado a apostar fortemente no Turbopack, que melhorou muito. Não se tratava de uma reclamação sobre desempenho. Para nós, a diferença maior era o ecossistema. O Vite já era a base comum da maior parte do nosso código de frontend, com um ecossistema de plugins mais amplo e configurações mais reutilizáveis entre projetos.

Portanto, manter o Next.js no Cloudflare resolveria parte do problema de hospedagem, mas preservaria tanto o desencontro entre frameworks quanto um ecossistema separado de ferramentas de build.

Então demos um passo atrás e analisamos o que cada tipo de aplicação realmente precisava.

Dividimos a stack por tipo de aplicação

Quando paramos de procurar um substituto universal para o Next.js, a arquitetura ficou muito mais simples.

Nossos sites de marketing precisavam de SSR porque têm páginas públicas e localizadas, metadados, URLs canônicas, sitemaps e tráfego vindo de mecanismos de busca.

A maioria dos outros aplicativos web não precisava de SSR e poderia simplesmente ser feita com Vite e TanStack Router.

Nossas APIs não precisavam de um framework React e se adequavam melhor a um runtime Node.js convencional.

A divisão final ficou assim:

Aplicativos web
Vite + TanStack Router
        │
        └── Cloudflare Workers

Sites de marketing
TanStack Start + SSR
        │
        └── Cloudflare Workers

APIs
Hono + tRPC
        │
        └── Railway / contêineres Node.js

A regra ficou simples: usar SSR onde ele oferece valor real, usar uma SPA simples onde não oferece e executar serviços de backend em um runtime de backend.

A maioria dos aplicativos web virou SPA

As migrações para SPA foram a parte mais fácil.

A migração do aplicativo web da WebCatalog foi particularmente rápida: criamos a estrutura inicial da versão substituta com Vite + TanStack Router, portamos a interface, mudamos o deploy para o Cloudflare Workers e removemos a antiga versão em Next.js na mesma manhã.

Repetimos o mesmo padrão para o aplicativo web da Lexibird, as configurações de conta, nosso console de desenvolvedores, a autenticação e os aplicativos administrativos. Desde a criação da estrutura inicial da primeira SPA até a exclusão do último aplicativo Next.js, passaram-se cerca de 19 dias.

Para esses aplicativos, o Cloudflare Workers é intencionalmente descomplicado. O Vite gera os arquivos estáticos, o Cloudflare os serve e as rotas do aplicativo recorrem a index.html como fallback. Não há runtime de SSR porque nada precisa de renderização no servidor.

A parte mais difícil foi preservar o comportamento que havia se acumulado em torno desses aplicativos ao longo do tempo. Algumas partes da lógica de autenticação tiveram de sair das rotas de servidor do Next.js e ir para a API, e versões antigas do aplicativo desktop da WebCatalog ainda dependiam de endpoints legados que precisávamos manter funcionando.

Mover a interface React foi fácil.

Preservar os contratos foi mais difícil.

Experimentamos o Astro e o descartamos cinco dias depois

Os sites de marketing foram mais difíceis.

Nossa primeira escolha foi o Astro, que parecia uma opção natural para webcatalog.io e lexibird.com porque ambos são sites públicos com muito conteúdo, e o Astro se integra bem ao Cloudflare.

Começamos a portar os dois sites e, cinco dias depois, paramos.

Não houve uma única falha fatal. Em vez disso, pequenas incompatibilidades foram se acumulando. Algumas rotas precisavam acessar o banco de dados durante a pré-renderização, enquanto nosso ambiente de build intencionalmente não tinha credenciais de produção para o banco. As ilhas React tornavam menos natural o compartilhamento do estado da aplicação. Também encontramos diferenças entre rotas pré-renderizadas e rotas renderizadas em tempo de execução, além de alguns atritos com as ferramentas do nosso repositório.

Nenhum desses problemas era impossível de resolver. Era exatamente por isso que continuar era perigoso. Poderíamos facilmente passar mais algumas semanas corrigindo uma coisa atrás da outra.

Em vez disso, apagamos a implementação e recomeçamos.

Os agentes de IA mudaram o cálculo dessa decisão. Uma grande parte do trabalho mecânico de migração não havia consumido semanas do tempo dos engenheiros, então o custo já incorrido era menor e ficou mais fácil admitir que preferíamos outra arquitetura.

O TanStack Start se encaixou melhor

Reiniciamos a migração dos sites de marketing a partir do código original em Next.js, desta vez usando TanStack Start.

Ele se encaixou de forma muito mais natural porque já usávamos TanStack Router nas SPAs. Assim, o roteamento, os loaders, os parâmetros de busca e a navegação seguiam conceitos semelhantes. O código continuava sendo React e TypeScript comuns, e o sistema de build era o Vite.

Portamos o lexibird.com para TanStack Start em um dia. O webcatalog.io veio em seguida.

A vantagem não era que o TanStack Start resolvesse magicamente todos os problemas. Era que ele se alinhava ao rumo que o restante da nossa stack já estava tomando.

Em um monorepo, isso importa. Compartilhar ferramentas de build significa mais plugins e configurações reutilizáveis, menos casos especiais na hora de depurar, menos alternância de contexto para os desenvolvedores e menos convenções específicas de cada projeto para os agentes de programação descobrirem.

O Cloudflare era muito mais barato para o nosso tráfego

A arquitetura foi apenas parte do motivo da queda na nossa fatura. Os preços do Cloudflare foram um fator importante, especialmente no que diz respeito à largura de banda.

Atualmente, o plano Workers Paid do Cloudflare cobra principalmente por requisições e uso de CPU e não adiciona cobranças por transferência de dados ou largura de banda para Workers. (developers.cloudflare.com) Isso faz muita diferença para sites públicos, pois uma requisição pode consumir pouquíssima CPU e ainda assim transferir HTML, JavaScript, imagens, fontes e outros arquivos.

O modelo de preços da Vercel também inclui categorias de uso e franquias relacionadas à rede, como Fast Data Transfer e Fast Origin Transfer. (vercel.com) Para o nosso perfil de tráfego, os custos do Cloudflare eram significativamente menores.

A economia não veio apenas da troca de provedor. Também transformamos muitos aplicativos em builds estáticos do Vite, reduzimos SSR desnecessário, tornamos o cache mais explícito e transferimos as APIs para um runtime mais adequado a elas. Mas os preços do Cloudflare, especialmente os relacionados à largura de banda, foram um fator importante na redução de cerca de 80% que observamos.

Esse número é específico da nossa carga de trabalho. Não estamos afirmando que qualquer aplicativo que migre da Vercel para o Cloudflare economizará 80%.

As APIs acabaram no Railway

As APIs eram um problema à parte.

Apesar de serem projetos Next.js, elas já eram, em grande parte, independentes dele. A API da WebCatalog tinha cerca de 34.000 linhas, mas apenas sete arquivos importavam next/server. O tRPC já usava seu adaptador Fetch, e o Inngest oferecia suporte ao Hono.

Substituímos a camada HTTP do Next.js por Hono. Essa parte foi surpreendentemente pequena.

A questão mais difícil era onde executá-la. Workers comuns não eram uma boa opção porque as APIs usam Node.js e dependências nativas como sharp.

Inicialmente, experimentamos o Cloudflare Containers, o que nos permitiu sair rapidamente da Vercel. Mas, depois de usar essa configuração em produção, descobrimos que o modelo operacional exigia mais ajustes manuais de capacidade do que queríamos naquele momento.

Então migramos as APIs mais uma vez.

Hoje, elas rodam no Railway como serviços convencionais em contêineres Node.js de longa duração. A CI (integração contínua) cria as imagens Docker e as envia para o nosso registro, e o Railway cuida do escalonamento horizontal automático.

Nem tudo precisa rodar na borda da rede.

Sair da Vercel significou assumir mais responsabilidades

O custo menor veio acompanhado de uma contrapartida.

A Vercel e o Next.js cuidavam de muitos aspectos da infraestrutura em um nível mais alto. Com TanStack Start e Workers, passamos a usar cache HTTP explícito. Uma página é renderizada, retornamos cabeçalhos de cache e o Cloudflare armazena a resposta em cache. O cache do navegador e o da borda podem seguir políticas diferentes, incluindo o comportamento stale-while-revalidate na borda.

Gostamos de tornar essas decisões explícitas, mas uma infraestrutura explícita também significa que os erros são seus.

Cometemos alguns. Uma regra de cache em produção acabou abrangendo, por engano, respostas de funções de servidor do TanStack específicas de cada visitante, e outra configuração de cache interagiu mal com o comportamento de fallback da SPA. Esses bugs foram lembretes úteis de que não é possível comprovar a correção de uma migração apenas examinando o repositório. A infraestrutura de produção também faz parte do sistema.

Os agentes de IA mudaram a forma como migramos

A maior parte do trabalho de implementação foi realizada por agentes de programação, principalmente Claude Fable 5 e Claude Opus 5.

Migrações de framework são particularmente adequadas para agentes porque boa parte do trabalho tem uma referência existente clara. Mova esta rota, preserve esta URL, substitua esta API do framework, mantenha os mesmos metadados, execute a verificação de tipos, corrija os erros e compare o resultado com a implementação antiga.

Para o webcatalog.io, mantivemos um controle da migração que dividia o trabalho em etapas como base, páginas de produto, páginas de catálogo, busca, blog, preços, redirecionamentos, sitemaps e transição para a nova versão. Em vez de pedir a um agente que “migrasse o webcatalog.io para TanStack Start”, demos a ele tarefas delimitadas, com requisitos explícitos que não poderiam mudar.

O aplicativo existente se tornou a especificação. O trabalho do agente era reproduzir o comportamento usando a nova arquitetura, não reinventar o produto.

Isso deslocou o esforço humano da tradução manual de código para perguntas como: esta página realmente deve usar SSR? Qual comportamento é intencional? O que pode ser armazenado em cache globalmente? Quais URLs precisam permanecer idênticas? Onde a autenticação deve acontecer? Quando devemos parar de tentar fazer uma abordagem funcionar?

Ainda revisamos o resultado, executamos builds e verificações de tipos e conferimos manualmente áreas de maior risco, como autenticação, SEO (otimização para mecanismos de busca), redirecionamentos e cache.

A mudança importante não foi a IA escrever código para nós. Foi a IA tornar a experimentação mais barata.

Experimentar o Astro e descartá-lo após cinco dias ficou muito mais fácil de justificar. Migrar as APIs uma vez e depois decidir que outra plataforma era mais adequada foi menos doloroso. O trabalho mecânico ficou mais barato, então pudemos mudar de direção quando a arquitetura estava errada, em vez de continuar apenas porque já havíamos investido demais nela.

Os agentes tornaram a implementação menos escassa.

Isso tornou a arquitetura, as restrições, a revisão e a verificação mais importantes.

Os 80% chegaram a aproximadamente 90%

Depois da migração, nosso custo de infraestrutura web estava cerca de 80% menor.

Então começamos a prestar mais atenção em quais requisições sequer chegavam aos aplicativos.

Uma parcela relevante do tráfego da internet pública é automatizada: mecanismos de busca, rastreadores de IA, agentes, scrapers, scanners e bots menos amigáveis. Parte desse tráfego é útil; outra parte, não.

Com os aplicativos diretamente por trás do Cloudflare, reforçamos nossas regras de segurança para que o tráfego automatizado hostil pudesse ser rejeitado na borda da rede, antes de acionar o processamento dos aplicativos ou consultas ao banco de dados.

Depois disso, nossa economia total chegou a aproximadamente 90% em comparação com a configuração antiga.

A redução final resultou de vários fatores atuando juntos: os preços mais baixos do Cloudflare, especialmente para largura de banda; menos trabalho no servidor; um runtime mais adequado para nossas APIs; cache mais explícito; e menos requisições desnecessárias chegando aos aplicativos.

Onde chegamos

Não restam aplicativos Next.js em nosso repositório. A maioria dos nossos aplicativos web agora são SPAs com Vite + TanStack Router no Cloudflare Workers. O webcatalog.io e o lexibird.com usam TanStack Start no Cloudflare Workers porque esses sites realmente se beneficiam de SSR. Nossas APIs usam Hono + tRPC no Railway, rodando em contêineres Node.js convencionais. Quase todos os nossos projetos de frontend agora fazem parte do ecossistema Vite.

Nosso custo de infraestrutura caiu cerca de 80%, em grande parte graças aos custos significativamente menores do Cloudflare para o nosso tráfego, especialmente no que diz respeito à largura de banda. Filtrar tráfego automatizado hostil na borda elevou a economia geral para aproximadamente 90%.

Mas o resultado que mais importa para nós é arquitetural. Os sites de marketing usam SSR, tudo o que pode ser uma SPA é uma SPA, e as APIs rodam em servidores de verdade quando servidores de verdade são a opção mais simples.

Começamos tentando baratear a Vercel.

Terminamos percebendo que não precisávamos da maior parte da arquitetura pela qual estávamos pagando.