Deploy de Laravel em produção em 2026: Forge, Cloud, Sail ou Kubernetes?
Deploy de Laravel em produção em 2026: Forge, Cloud, Sail ou Kubernetes?
Tem uma pergunta que toda vez que aparece num grupo de Laravel destrava trinta respostas em meia hora e nenhuma fecha o assunto.
"Onde eu rodo esse app em produção?"
A resposta honesta em 2026 é que você tem quatro caminhos viáveis, cada um resolvendo um problema diferente, e uma armadilha que vai destruir seu banco se você cair nela. Forge ainda é o default sensato pra time pequeno. Laravel Cloud virou o caminho óbvio pra app com pico imprevisível. Sail + VPS próprio com FrankenPHP te dá margem absurda e força a entender Docker direito. Kubernetes só faz sentido em um cenário muito específico, e provavelmente não é o seu.
Neste post você vai ver quando escolher cada um, o que muda no fluxo de deploy, qual é a armadilha do serverless puro com Eloquent, e um checklist de 18 itens que você roda antes de cantar vitória no go-live.
TL;DR
- O que é: matriz comparativa dos quatro caminhos de deploy de Laravel em produção em 2026.
- Stack/Modelos: Laravel 12 + PHP 8.3, Octane com FrankenPHP/Swoole, MySQL ou Postgres, Redis/Valkey.
- Custo/Acesso: Forge a partir de $19/mês + VPS, Laravel Cloud com Starter gratuito pay-as-you-go, Sail + VPS próprio na faixa de $5 a $40/mês de máquina, Kubernetes quase sempre custa mais que parece.
- Link útil: Laravel Cloud Compute e Forge Docs.
O contexto: por que essa decisão pesa em 2026
A escolha de onde rodar Laravel mudou de natureza nos últimos dois anos.
Antes era uma decisão de infra. Hoje é uma decisão de produto.
O motivo é que três coisas aconteceram quase ao mesmo tempo. Octane com FrankenPHP virou maduro o suficiente pra ser default em projeto novo, com benchmarks mostrando salto de 400 req/s pra mais de 6 mil req/s no mesmo hardware quando você sai de PHP-FPM puro. Laravel Cloud chegou no GA e ofereceu uma promessa nova: autoscale gerenciado com scale-to-zero medido em milissegundos, eliminando o trade-off histórico entre "deixo idle e pago" ou "desligo e o usuário espera o cold start". E a conta de cloud bruta subiu o suficiente pra fazer time pequeno reconsiderar Hetzner com VPS de €5/mês.
Se você ainda decide infra pelo "o que o último projeto usou", você está pagando caro em pelo menos uma dimensão: dinheiro, tempo de deploy ou risco operacional.
Os quatro caminhos viáveis
Forge: o default sensato
Forge continua sendo a escolha certa pra 80% dos projetos Laravel em produção.
Você liga numa cloud (DigitalOcean, Hetzner, AWS, Vultr), o Forge provisiona o servidor com Nginx, PHP 8.3, MySQL, Redis e Supervisor já configurados, e te dá um botão de "Deploy". Custa $19/mês de Forge + o preço da máquina, então com um VPS Hetzner de €5/mês você sai por uns $25/mês pra rodar um app que aguenta tranquilamente até uns 50 mil requests por dia bem distribuídos.
O fluxo de deploy padrão usa as macros do próprio Forge:
cd $FORGE_PATH
git pull origin $FORGE_SITE_BRANCH
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
if [ -f artisan ]; then
$FORGE_PHP artisan migrate --force
$FORGE_PHP artisan config:cache
$FORGE_PHP artisan route:cache
$FORGE_PHP artisan view:cache
$FORGE_PHP artisan event:cache
fi
( flock -w 10 9 || exit 1
echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock
Se você ativar zero-downtime deployment, o Forge cria um diretório novo a cada release, roda tudo nele, e só no final faz o swap do symlink. Mantém os últimos 4 releases por padrão pra rollback rápido. Reload do FPM deixa de ser necessário, porque cada release vive em pasta própria e o OPcache não cacheia nada antigo.
A pegadinha que pega todo mundo a primeira vez: zero-downtime resolve o lado da aplicação, não o lado do banco. Se sua migration adiciona uma coluna NOT NULL sem default e seu código novo já escreve nela, o release antigo (que roda por alguns segundos durante o swap) vai começar a estourar exception. Regra simples: migration sempre vai numa direção compatível com o código anterior, e a coluna vira NOT NULL numa segunda migration depois que o release novo está estável.
Use Forge quando: time pequeno (até 3 devs no backend), tráfego razoavelmente previsível, latência aceitável de ~80-150ms, você quer um servidor que sabe o nome e onde fazer SSH quando precisa entender o que está acontecendo.
Não use Forge quando: seu tráfego tem picos de 50x em 10 minutos (live de influencer, BlackFriday, lançamento), ou você não quer pensar em capacidade nunca.
Laravel Cloud: quando o pico mata o servidor
Laravel Cloud é o que você quer quando o problema deixa de ser "como faço deploy" e vira "como sobrevivo ao pico de quinta-feira".
Os planos são três. Starter é gratuito com pay-as-you-go. Growth sai por $20/mês mais uso e te dá autoscale de 1x a 10x. Business é $200/mês mais uso e libera autoscale ilimitado e agendado, que é o que você usa pra subir capacidade antes da campanha começar em vez de durante.
O que faz Laravel Cloud diferente de "subi numa cloud qualquer" são três coisas concretas:
Primeiro, scale-to-zero real. A aplicação hiberna quando não tem tráfego, e o wake-up agora é em milissegundos (antes era 5 a 20 segundos, o que matava qualquer caso de uso de produção). Pra projeto interno, ambiente de staging, side project que ninguém usa de madrugada, isso é dinheiro voltando direto pro seu bolso.
Segundo, queue clusters que escalam workers sozinhos olhando CPU, memória, throughput e backlog. Você para de errar dimensionamento de Horizon na unha.
Terceiro, ambiente de preview por pull request. Cada PR sobe num ambiente isolado, com banco próprio, pra QA testar. Em time de produto, isso muda o ciclo de review de "vou clonar e rodar local" pra "abre o link e mexe".
O vapor.yml morreu, o equivalente agora é cloud.yaml:
name: meu-app
environments:
production:
compute:
type: web
size: standard-1
autoscale:
min: 1
max: 8
metric: cpu
target: 70
queue:
cluster: true
workers:
min: 1
max: 20
deploy:
- 'php artisan migrate --force'
- 'php artisan config:cache'
- 'php artisan route:cache'
Use Laravel Cloud quando: seu tráfego tem cara de montanha-russa, você não tem (nem quer ter) alguém de DevOps no time, ou você precisa de ambientes de preview por PR pra acelerar QA.
Não use Laravel Cloud quando: seu custo de cloud já é uma linha sensível no P&L. O modelo pay-as-you-go é honesto, mas previsível ele não é, e isso pode complicar fechamento de mês.
Sail + VPS próprio com Docker: margem e aprendizado
Esse é o caminho que ninguém da Laravel oficialmente recomenda e que é o mais educativo dos quatro.
A regra de ouro: Sail é dev, não produção. O container do Sail usa artisan serve, que roda um único processo single-threaded e desmaia em qualquer carga real. O que você faz é manter o docker-compose.yml do Sail pro dev e escrever um docker-compose.prod.yml separado, com FrankenPHP ou PHP-FPM + Nginx, otimizado pra produção.
A vantagem é dupla. Você paga uns $5-$20/mês de VPS Hetzner ou Contabo e roda um app que aguenta tráfego respeitável. E você aprende Docker direito, que é uma skill que paga dividendos pelo resto da sua carreira de backend.
Um Dockerfile enxuto pra produção com FrankenPHP:
FROM dunglas/frankenphp:1-php8.3-alpine AS base
WORKDIR /app
RUN install-php-extensions \
pdo_mysql \
redis \
opcache \
intl \
zip \
bcmath
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative \
&& php artisan config:cache \
&& php artisan route:cache \
&& php artisan view:cache \
&& php artisan event:cache
ENV SERVER_NAME=:80
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]
E o docker-compose.prod.yml típico:
services:
app:
build: .
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- APP_ENV=production
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: mysql:8.4
restart: unless-stopped
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis-data:/data
volumes:
mysql-data:
redis-data:
CI/CD você monta no GitHub Actions com docker build + docker push pra um registry, SSH no servidor, docker compose pull && docker compose up -d. Vinte linhas de YAML, sem mágica.
O que te morde nesse caminho: você é o sysadmin agora. Backup do volume do MySQL, rotação de log, monitoramento de disco, renovação de TLS (use Caddy ou Traefik que faz sozinho), update de imagem base quando sai patch de segurança do PHP. Não é difícil, mas é trabalho contínuo.
Use Sail + VPS quando: você quer custo mínimo, está confortável com Linux + Docker, ou está usando o projeto pra aprender DevOps de verdade.
Não use quando: o app é crítico pra receita da empresa e você não tem ninguém de plantão pra responder quando o disco encher às 3 da manhã.
Kubernetes: quase nunca, e o quase importa
Vou ser direto. Se você está pensando em Kubernetes pra rodar Laravel, na esmagadora maioria dos casos a resposta é não.
Kubernetes resolve um problema específico: orquestrar dezenas ou centenas de serviços, com requisitos de scaling diferentes, em múltiplas regiões, com time grande o suficiente pra ter alguém dedicado em SRE. Se sua descrição não bate com isso, a complexidade inicial de containerizar e configurar tudo vai te custar semanas de trabalho que nunca voltam em valor.
Os cenários onde Kubernetes faz sentido pra Laravel são poucos e específicos. Você já tem um cluster rodando pelos outros serviços da empresa e o Laravel é "mais um workload". Você precisa de multi-region com failover automático e regulação te força a controlar tudo. Você tem worker pools muito heterogêneos (transcoding de vídeo, ML inference, web requests) e quer compartilhar nós entre eles.
Pra qualquer outro caso, Helm chart de Laravel é overengineering. Você troca o problema de "fazer deploy" pelo problema de "manter Kubernetes funcionando", que é muito maior.
Se mesmo assim você decidiu ir, use um chart que já existe (tipo o renoki-co/laravel-helm-demo como referência), separe migrations num Job pré-deploy, configure HPA por CPU e memória, e tenha PodDisruptionBudget pra rolling update não derrubar o serviço durante deploy.
A armadilha: serverless puro frita o Eloquent
Aqui é o lugar onde eu mais vejo time bom tomar pancada feia.
A ideia de rodar Laravel "serverless de verdade" (cada request num Lambda novo) é tentadora. Paga só pelo que usa, escala automaticamente, sem servidor pra cuidar.
O problema é que Eloquent assume conexão persistente com o banco. Cada invocação Lambda abre uma conexão MySQL nova. Multiplica por 1000 invocações simultâneas e seu RDS db.t3.medium aceita 90 conexões. Resultado previsível: "SQLSTATE[HY000] [1040] Too many connections", banco no chão, aplicação fora.
O Vapor mitiga isso com RDS Proxy, que funciona como pool de conexão na frente do banco. Você ativa via vapor.yml com database-proxy: true e a coisa para de explodir. Mas RDS Proxy custa $0.015/hora por vCPU do banco (uns $20-$50/mês a mais) e adiciona latência de uns 5-15ms em cada query.
A lição é que serverless puro é incompatível com a forma como ORM relacional foi desenhado. Você ou paga o tax do connection pooler externo (Vapor + RDS Proxy, ou PgBouncer/ProxySQL em VPS), ou aceita que vai ter caos em pico.
Laravel Cloud resolveu isso elegantemente fazendo containers de longa duração com warm pool, em vez de Lambda puro. Você ganha o autoscale sem comprar o problema de conexão. Foi a decisão de arquitetura certa, e é parte do porquê Cloud ganhou tração.
Checklist de 18 itens antes do go-live
Independente do caminho, antes de abrir tráfego em produção rode esse checklist. Cada item já me salvou de pelo menos um incidente.
Performance:
php artisan config:cacherodando em todo deploy.php artisan route:cacherodando em todo deploy.php artisan view:cacherodando em todo deploy.php artisan event:cacherodando em todo deploy.composer install --no-dev --optimize-autoloader --classmap-authoritative.- OPcache ativado com
opcache.memory_consumption=256eopcache.validate_timestamps=0. - Octane rodando com FrankenPHP ou Swoole se a aplicação tem latência crítica.
Banco e cache:
8. APP_DEBUG=false confirmado no .env de produção.
9. Connection pooler configurado se for serverless (RDS Proxy, PgBouncer, ProxySQL).
10. Backup automático do banco com restore testado (não basta ter backup, tem que ter restaurado uma vez).
11. Redis ou Valkey separado pra cache + sessions + queue, não tudo no mesmo banco.
Observabilidade:
12. Log centralizado fora do servidor (Papertrail, BetterStack, Loki). Log local some quando o disco enche.
13. Error tracking (Sentry, Flare, Bugsnag) com release tag por deploy.
14. Health check endpoint (/health ou /up) que valida banco e cache, não só "200 OK".
15. Uptime monitoring externo (UptimeRobot, Better Uptime) batendo no health check.
Segurança e operação:
16. HTTPS forçado com redirect 301 e HSTS header ativado.
17. Rate limiting nas rotas de auth e nas APIs públicas (throttle:60,1 no mínimo).
18. Plano de rollback documentado e testado. Quem aperta qual botão quando o deploy quebra às 23h?
Se um desses estiver vermelho, o go-live espera.
FAQ rápido
Devo migrar meu app antigo do Forge pra Laravel Cloud?
Depende de duas coisas. Se seu tráfego é estável e você está confortável com sua máquina, fique. Se você está pagando idle (servidor superprovisionado pra picos raros) ou tendo dor de capacity planning, Cloud paga a diferença em semanas.
Octane com FrankenPHP funciona com qualquer pacote Laravel?
Quase. A regra é: pacote que faz state global ou usa singleton sem reset entre requests vai dar problema. A maioria dos pacotes populares já se ajustou, mas teste em staging antes. Stripe SDK, Sentry, Telescope (em dev) costumam ser os que pedem ajuste.
Posso usar Sail no servidor de produção mesmo?
Tecnicamente sim, na prática vai ser ruim. O container do Sail usa artisan serve que é single-threaded e não foi feito pra carga. Use FrankenPHP ou PHP-FPM + Nginx em produção, mantenha Sail só pro dev.
Vale a pena migrar pra PHP 8.4 ou ficar no 8.3?
Em 2026, PHP 8.3 ainda é o sweet spot pra produção. 8.4 está estável mas alguns pacotes ainda não cobriram 100%. Se você está começando agora, vai de 8.3. Se já está em 8.3 estável, não tem urgência.
Conclusão
A decisão de onde rodar Laravel deixou de ser uma escolha técnica binária e virou uma decisão de produto: você está otimizando custo, tempo de operação, ou capacidade de absorver pico?
Pra time pequeno com tráfego previsível, Forge é o default e provavelmente vai ser pelos próximos cinco anos. Pra app com pico que mata servidor estático, Laravel Cloud é a resposta certa em 2026, e o scale-to-zero em milissegundos fechou o último argumento contra. Sail + VPS próprio é o caminho de quem quer margem e está disposto a ser sysadmin. Kubernetes é quase sempre overengineering, mas o quase importa quando se aplica.
Se você está construindo IA em produção e quer trocar ideia com outros devs PHP/Laravel e engenheiros de IA que estão tomando essas mesmas decisões na prática, dá uma passada na Beer and Code, a melhor comunidade de AI engineering em português, com grupo no WhatsApp aberto pra quem está construindo IA em produção.
Agora pega o checklist, roda nos 18 itens, e só depois aperta o deploy.
{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.
Você também pode gostar
Como alcancei pontuações quase perfeitas no Google Lighthouse em um blog feito com Laravel / Filament
Veja como consegui atingir pontuações acima de 90 no Google Lighthouse, melhorando drasticamente o desempenho dos meus sites e proporcionando uma experiência excepcional para os usuários.
Como Implementar um Sistema de Recomendação Semântica no Laravel com Embeddings (Sem Tags, Sem Categorias)
Aprenda como construir um sistema de recomendação semântica real no Laravel, usando embeddings e PostgreSQL (pgvector) — sem depender de categorias, tags ou heurísticas frágeis.
Laravel AI SDK chegou: vale migrar do Prism (ou do seu wrapper)?
Laravel AI SDK saiu em fevereiro/2026 e ficou estável em março, junto com o Laravel 13. Portei um projeto real de Prism pra SDK oficial: 47 linhas a menos, switch de provider em uma atribuição, embeddings e vector store first-party. O diff aberto, o que continua valendo no Prism e quando não migrar.
Otimize sua aplicação Laravel com o novo Memoized Cache Driver (Laravel 12.9)
O Laravel 12.9 trouxe uma novidade poderosa: o Memoized Cache Driver. Essa feature otimiza o desempenho das aplicações ao armazenar em memória os valores obtidos do cache durante o tempo de execução da requisição, evitando múltiplos acessos ao cache.