Kamal ou PaaS? Onde fazer deploy de uma app Rails 8 em 2026
TL;DR
Para a maioria das apps Rails 8 em 2026, Kamal em uma ou duas VPS é o padrão que vale testar primeiro: vem com o Rails, custa uma fração de um PaaS e já está maduro. Escolha uma plataforma gerenciada quando ninguém no time quiser cuidar de backups, patches e plantão do próprio servidor.
O Heroku entrou em modo manutenção e o Rails 8 já vem com o Kamal. Veja como decidir entre sua própria VPS e uma plataforma gerenciada, com um deploy.yml pronto para produção.
Duas coisas mudaram a conversa sobre deploy de Rails. Em 6 de fevereiro de 2026, o Heroku anunciou a transição para um "sustaining engineering model": a plataforma continua com suporte, mas não terá novas funcionalidades nem novos contratos Enterprise para novos clientes. Enquanto isso, o Kamal, que já vem em toda app Rails 8 nova, chegou à versão 2.12 em junho, com suporte nativo a OpenTelemetry nos logs de deploy.
Então a pergunta para uma app nova, ou para uma app no Heroku procurando a próxima casa, não é mais "qual PaaS?". É "eu quero ter um servidor ou não?"
Recentemente migrei este blog para Kamal em uma única VPS, com Postgres rodando como accessory do Kamal e imagens no Docker Hub. Este post é o framework de decisão que eu gostaria de ter tido antes de começar.
A resposta curta
- Kamal na sua própria VPS se alguém do time domina Linux, SSH e backups, e você quer custo previsível.
- Um PaaS gerenciado (Render, Fly.io, Heroku) se ninguém quer ser acordado porque um disco encheu, ou se você precisa de Postgres gerenciado com point-in-time recovery desde o primeiro dia.
- Sua própria conta na nuvem (ECS, Beanstalk) se você já está na AWS com requisitos de compliance, VPC peering e um time de plataforma. O Kamal também faz deploy em EC2, mas os serviços gerenciados da AWS trazem autoscaling e integração com IAM.
O que o Kamal realmente entrega
O Kamal não é uma plataforma, é uma ferramenta de deploy. Ele acessa seus hosts via SSH, baixa a imagem Docker que você construiu, sobe o novo container, espera o health check e troca o tráfego pelo kamal-proxy sem downtime. O kamal-proxy também cuida dos certificados Let's Encrypt.
O que o Rails 8 já traz pronto:
- Um
Dockerfilede produção com jemalloc e Thruster na frente do Puma config/deploy.ymle.kamal/secrets- A rota de health check
/up - Solid Queue, Solid Cache e Solid Cable, então você não precisa de Redis para jobs, cache ou Action Cable
Esse último ponto importa mais que o próprio Kamal. Uma app Rails 8 com o trio Solid precisa de um container web e um banco de dados. Só isso. Menos peças móveis é o que torna uma única VPS realista.
O que um PaaS entrega e o Kamal não
Seja honesto com esta lista antes de escolher:
- Banco gerenciado. Backups automáticos, point-in-time recovery, failover, upgrades de versão menor. Com um accessory do Kamal, tudo isso é com você.
- Patches do sistema operacional. Alguém precisa rodar
unattended-upgradese reiniciar para correções de kernel. - Autoscaling horizontal. O Kamal faz deploy nos hosts que você lista. Mais capacidade significa provisionar uma máquina e editar o
deploy.yml. - Observabilidade integrada. Log drains, métricas e alertas são um checkbox num PaaS. Numa VPS você mesmo configura o agente de APM e o envio de logs.
- Sem ponto único de falha por padrão. Uma VPS é uma máquina. Se ela morrer, você fica fora do ar até reconstruir.
Nada disso é difícil. É apenas trabalho, e num PaaS outra pessoa faz esse trabalho por você.
Um deploy.yml de produção
Este é próximo do que roda este blog: um host web, Postgres como accessory na mesma máquina, Solid Queue dentro do Puma.
service: myapp
image: myuser/myapp
servers:
web:
- 203.0.113.10
proxy:
ssl: true
host: myapp.com
registry:
username: myuser
password:
- KAMAL_REGISTRY_PASSWORD
builder:
arch: amd64
env:
secret:
- RAILS_MASTER_KEY
- POSTGRES_PASSWORD
clear:
SOLID_QUEUE_IN_PUMA: true
DB_HOST: myapp-db
WEB_CONCURRENCY: 2
volumes:
- "myapp_storage:/rails/storage"
asset_path: /rails/public/assets
accessories:
db:
image: postgres:17
host: 203.0.113.10
port: "127.0.0.1:5432:5432"
env:
clear:
POSTGRES_USER: myapp
POSTGRES_DB: myapp_production
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
E o .kamal/secrets:
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
RAILS_MASTER_KEY=$(cat config/master.key)
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
Alguns detalhes que pegam muita gente:
DB_HOST: myapp-db: accessories entram na rede Dockerkamalcomo<service>-<accessory>. Seudatabase.ymldeve lerENV["DB_HOST"].- Faça o bind do banco em
127.0.0.1. Publicar a 5432 em todas as interfaces coloca o Postgres na internet, e as regras de iptables do Docker passam por cima do UFW. asset_pathmantém os assets antigos com fingerprint disponíveis durante a troca, então quem está navegando no meio do deploy não recebe 404 no CSS.builder.arch: amd64importa no Apple Silicon. Sem isso, você gera uma imagem ARM para um servidor x86. Use um remote builder se a emulação local for lenta demais.
O primeiro deploy é kamal setup. Depois disso, kamal deploy. kamal app logs -f e kamal console (se você mantiver os aliases padrão) cobrem o dia a dia.
As partes que agora são suas
Se for de Kamal, faça isto no primeiro dia, não depois do primeiro incidente:
Backups fora da máquina. Um pg_dump noturno enviado para o S3 (ou qualquer object storage) é o mínimo. Teste um restore. Um banco como accessory sem backup externo está a um disco de perder tudo.
Active Storage fora da máquina. O volume myapp_storage serve para SQLite ou uma app de brinquedo. Para uploads de usuários em produção, aponte o Active Storage para o S3 e mantenha o servidor descartável.
Monitoramento. Envie métricas da app com o APM de sua preferência e adicione um uptime check externo no /up. O suporte a OpenTelemetry do Kamal 2.12 cobre os logs de deploy, não a telemetria da aplicação.
Patches. Ative atualizações de segurança automáticas e agende reboots. Mantenha o SSH só com chave.
Simulado de reconstrução. Uma vez, provisione uma VPS nova e faça deploy do zero. Se levar uma hora, seu RTO é uma hora.
Custo, por alto
Não vou citar preços exatos, porque eles mudam a cada poucos meses. O formato é estável: uma VPS intermediária na Hetzner, DigitalOcean ou similar costuma custar mais ou menos o mesmo que um dyno web pequeno somado a um banco gerenciado pequeno num PaaS, mas entrega várias vezes mais CPU e RAM. A diferença cresce conforme você adiciona workers e memória, porque num PaaS cada tipo de processo é cobrado separado e numa VPS todos dividem a máquina.
O custo escondido é o seu tempo. Se você cobra por hora, duas horas por mês cuidando do servidor podem apagar a economia de uma app pequena.
Saindo do Heroku para o Kamal: checklist
- Atualize para Rails 8 (ou adicione Kamal e um Dockerfile a uma app 7.1+ com
bundle add kamal && kamal init). - Troque as peças que dependem de Redis por Solid Queue, Solid Cache e Solid Cable se quiser um setup de dois containers. O Sidekiq continua funcionando bem como um role separado no Kamal, se preferir.
- Transforme seu
Procfileem roles do Kamal:web, ejobcomcmd: bin/jobsse você não roda jobs dentro do Puma. - Mova as config vars para o
.kamal/secrets(vindas do 1Password, Bitwarden ou variáveis de ambiente, nunca commitadas). pg_dumpdo Heroku Postgres,pg_restoreno accessory ou num banco gerenciado.- Reduza o TTL do DNS um dia antes, faça o deploy, valide e só então troque o registro.
- Mantenha a app do Heroku com escala mínima, mas viva, por uma semana como caminho de rollback.
Onde um PaaS ainda ganha
Não deixe o entusiasmo com o Kamal te empurrar para cuidar de servidores que você não quer. Um PaaS é a melhor escolha quando:
- Ninguém no time quer plantão de infraestrutura.
- Você precisa de Postgres gerenciado com PITR e alta disponibilidade e não quer pagar um banco gerenciado separado ao lado da VPS (que, aliás, é um ótimo meio-termo).
- O tráfego tem picos grandes o suficiente para o autoscaling economizar dinheiro de verdade.
- Você precisa de latência multi-região, onde o modelo do Fly.io é realmente difícil de replicar com Kamal.
O Heroku em si não vai sumir amanhã. "Sustaining engineering" significa estável, não morto. Mas para uma app nova, escolher uma plataforma que parou publicamente de criar funcionalidades é difícil de justificar quando Render e Fly.io seguem em desenvolvimento ativo.
Minha recomendação
Comece apps Rails 8 novas com Kamal em uma VPS, um job de backup fora da máquina e S3 para uploads. Coloque o banco num serviço gerenciado no momento em que perder uma hora de dados passar a doer no negócio. Migre para um PaaS, ou para ECS na sua própria conta AWS, quando o tempo gasto com o servidor custar mais do que a fatura que você está evitando.
Fontes
- An Update on Heroku (blog do Heroku, 6 de fevereiro de 2026) www.heroku.com
- Simon Willison sobre o anúncio de sustaining engineering do Heroku simonwillison.net
- Releases do Kamal (v2.12.0) github.com
- Documentação do Kamal kamal-deploy.org
Perguntas frequentes
O Kamal está pronto para produção em 2026?
Sim. O Kamal vem em toda app Rails 8 nova, a 37signals roda os próprios produtos nele, e a versão 2.12 adicionou logs de deploy com OpenTelemetry, retry do lock de deploy e a opção stop_timeout.
O Heroku vai acabar?
Não. Em fevereiro de 2026 o Heroku passou para um modelo de sustaining engineering: continua com suporte, mas não desenvolve novas funcionalidades nem assina novos contratos Enterprise com novos clientes.
Posso rodar Postgres com o Kamal?
Sim, como um container accessory. Faça o bind em 127.0.0.1, conecte pelo hostname da rede Docker kamal e envie backups com pg_dump para fora do servidor. Para dados críticos, um banco gerenciado é mais seguro.
Preciso de Redis para fazer deploy de Rails 8 com Kamal?
Não. Solid Queue, Solid Cache e Solid Cable usam o seu banco, então um container web mais o Postgres bastam. Sidekiq e Redis continuam funcionando como roles e accessories extras no Kamal.
Comentários
Faça login com GitHub para comentar.
Ainda não há comentários.