Meu site é Next.js. Meu SaaS, o CourseShelf, é Elixir com Phoenix. Eu uso os dois lados da discussão sobre qual framework é melhor e começo por uma pergunta que costuma ficar de fora: onde esse código vai rodar?

Escolher a linguagem antes de responder isso deixa metade da decisão no escuro.

A pergunta antes da stack

Pra um SaaS serverless novo em JavaScript, meu voto é TanStack Start. Pra um app web complexo que mantém processos, conexões e jobs ativos, eu prefiro Elixir e Phoenix. São escolhas que vêm do funcionamento do produto.

No vídeo eu mostro a comparação com o código real dos meus projetos. Aqui vai a versão escrita.

https://www.youtube.com/watch?v=OM4kztBu-hY

O estático não precisa de uma guerra de frameworks

Se dá pra gerar HTML antes da visita, várias ferramentas resolvem. O critério é conseguir produzir os arquivos que seu produto precisa entregar.

Meu site busca estatísticas e vídeos do YouTube, mas não faz sentido consultar a API de novo a cada pessoa abrindo a home. Em src/data-access/youtube.ts, a função que calcula as estatísticas começa assim:

// bergholz.com.br/src/data-access/youtube.ts (início da função)
export const getChannelStats = async () => {
  "use cache"
  cacheLife("days")

  const response = await fetch(CHANNEL_URL, { next: { revalidate: 86400 } })

Esse trecho é só o começo da função real. O resto valida a resposta e soma os canais. O importante aqui é reutilizar o resultado, com atualização diária, em vez de fazer a mesma consulta pra cada visita.

Isso não torna o projeto um export puramente estático. O framework pode servir conteúdo pré-renderizado e atualizar os dados no servidor. No modelo de Cache Components do Next, a revalidação acontece conforme as requisições chegam, não num cron que precisa disparar exatamente a cada vinte e quatro horas.

Você consegue combinar partes prontas com partes dinâmicas no mesmo projeto. Não precisa escolher uma identidade “estática” ou “dinâmica” pra tudo que existe nele.

JavaScript joga em casa no Workers

O Cloudflare Workers executa código em isolates do V8, o motor de JavaScript também usado no Chrome. Não é um container novo com um processo Node pra cada aplicação.

O runtime foi pensado pra dividir a infraestrutura entre muitos ambientes isolados. Dá pra usar outras linguagens e WebAssembly, mas JavaScript é uma escolha natural ali.

Isso vem com limites. No plano gratuito do Workers, uma requisição HTTP tem dez milissegundos de CPU. Esperar a rede não conta como CPU, mas processar dados conta. O modelo favorece trabalho que recebe uma requisição, executa e responde, dentro do orçamento disponível.

E a linguagem é a mesma no front e no back. Um framework fullstack consegue ligar a chamada feita pela interface à função que executa no servidor, sem você manter uma API separada só pra conectar duas partes do próprio produto.

Por que eu começaria com TanStack Start

Gosto de como o TanStack Start explicita as server functions e aproveita o TanStack Router pra tipar rotas e parâmetros. Pra mim, isso deixa mais claro o que roda no servidor e o contrato que a interface está usando.

O Next resolve esse espaço com suas próprias convenções, incluindo Server Actions. Eu continuo usando no meu site. Só prefiro o modelo do TanStack pra começar um SaaS serverless novo.

A hospedagem também pesa. O plano Hobby da Vercel é pra uso pessoal e não comercial. Um SaaS cobrando clientes não deve fazer sua conta assumindo que fica nesse plano.

Dá pra levar Next pra Cloudflare com o OpenNext. É uma opção real, mas existe um adaptador no caminho. O deploy do TanStack Start no Workers usa o plugin da Cloudflare pro Vite.

Se o seu time já conhece Next, fica no Next. O ganho de trocar precisa justificar o trabalho. SvelteKit, Nuxt e React Router também oferecem outros caminhos fullstack; eu não escolheria React só pra poder usar o framework que citei.

Quando a aplicação precisa continuar acordada

Pensa no app de leituras do texto sobre hospedagem gratuita. Agora tem uma lista compartilhada com amigos, atualização em tempo real, busca de título e imagem em background e um e-mail semanal.

Dá pra fazer tudo isso em serverless. A Cloudflare tem Durable Objects pra estado e conexões, Queues pra filas e Cron Triggers pra agendamento. Mas entram outras peças, APIs e limites pra aprender.

No Elixir, processos leves e supervisão fazem parte do modelo da BEAM, a máquina virtual do Erlang. O Phoenix usa essa base pra web. Conexões, tarefas e serviços podem viver dentro da mesma aplicação e ser supervisionados ali.

No CourseShelf, o supervisor inicia a conexão com banco, PubSub, Oban, cache, Presence e o endpoint. O agendamento dos e-mails é configuração no mesmo projeto:

# courseshelf-v2/config/config.exs (entradas do crontab do Oban)
{"0 9 * * *", CourseShelf.Workers.EmailDigestWorker, args: %{frequency: "daily"}},
{"0 9 * * 1", CourseShelf.Workers.EmailDigestWorker, args: %{frequency: "weekly"}},
{"0 6 * * 6", CourseShelf.Workers.CatalogScoutWorker}

Essas entradas usam UTC. O scout roda sábado às seis UTC, três da manhã em São Paulo. O Oban usa o banco do projeto pra persistir os jobs; no meu caso, Postgres. Não precisei adicionar Redis pra essa fila.

É por isso que eu gosto de Phoenix num app complexo: essas necessidades se encaixam no mesmo modelo de aplicação.

As peças no mesmo projeto

Esse conforto tem uma conta

A BEAM tem muito valor quando sobe e continua de pé. Reiniciar toda a aplicação a cada requisição joga fora justamente a continuidade que eu quero aproveitar.

No fly.toml do CourseShelf, mantenho pelo menos uma máquina ativa:

# courseshelf-v2/fly.toml (dentro de http_service)
min_machines_running = 1

O cron do Oban depende da aplicação rodando. Se ela dormir, o processo que dispara o backup da madrugada também não está ativo.

E aí acaba a conta de hospedagem zero. O Fly não oferece uma franquia gratuita recorrente pra organizações novas. Em setembro de 2026, o consumo do app e do banco do CourseShelf somou US$ 26,03 antes de créditos, conforme a consulta usada no vídeo.

O app não está na menor máquina. Eu aumentei CPU depois de lentidão e memória depois de uma enxurrada de bots. É uma escolha baseada no que aconteceu no produto, não uma cotação de quanto todo projeto Phoenix vai custar.

Tem servidor gratuito que hiberna, como o web service Free do Render, após quinze minutos sem tráfego. Isso pode servir a outros usos, mas não entrega o processo contínuo que motivou a minha escolha aqui.

Minha escolha começa no funcionamento

O produto precisa de…Onde eu começaria
Arquivos que podem ficar prontos antesFerramenta que gere esses arquivos bem
Back-end sob demandaJavaScript/TypeScript; meu voto é TanStack Start
Processos contínuos, tempo real e jobs integradosElixir com Phoenix

JavaScript também roda num servidor contínuo. Outras linguagens também fazem serverless. Essa tabela mostra minhas preferências pra reduzir atrito, não uma limitação de onde cada linguagem pode executar.

Quando eu sei o que precisa continuar ativo e o que pode acontecer só na requisição, a escolha fica muito menor. O framework vem depois dessa resposta.

Vídeo no YouTube: Qual framework usar no seu SaaS?

Conheça meu trabalho: https://bergholz.com.br/

Obrigado por ler até aqui.

The end