Skip to main content
business and corporate websitesbusiness and corporate website packagesbusiness and corporate website designwebsite design business and corporatewebsite business and corporatebest business and corporate websitesbusiness and corporate website and seoannual website packagesprofessional website design mumbai

Laravel Deployment and Hosting: Cloud, Forge, VPS, Docker, and Octane

Published: July 9, 2026
Written by Sumeet Shroff
Uncategorized
07.09.26
Laravel Deployment and Hosting: Cloud, Forge, VPS, Docker, and Octane

Laravel deployment offers numerous options, each with potential pitfalls. Whether deploying a Laravel 12 or 13 application for the first time or migrating from a VPS, your choices in hosting, process management, and zero-downtime strategy will impact your app's reliability. This guide explores major deployment paths for 2025-26: Laravel Cloud, Laravel Forge (with Laravel VPS integration), self-managed VPS, Docker, Laravel Octane (FrankenPHP, Swoole, RoadRunner), and Laravel Vapor. By the end, you'll know which stack suits your project, budget, and team's skills.

For app speed optimization, read our Laravel performance optimization guide alongside this one — deployment strategy and performance tuning are interconnected.

Need a Laravel application deployed, scaled, and secured by a team with nearly three decades of experience in Mumbai? We handle end-to-end custom web application delivery.

Explore Our Laravel Development Services

Prerequisites and Version Requirements

Laravel 12, released on 24 February 2025, requires PHP 8.2 or higher (PHP 8.3 recommended). Laravel 13, released on 17 March 2026, requires PHP 8.3 minimum. Ensure your server or container image supports the correct PHP version before deployment.

Additional composer requirements before upgrading:

  • Carbon 3.x is mandatory for Laravel 12+. Update "nesbot/carbon": "^2.0" to "^3.0" in composer.json to avoid dependency issues.
  • Laravel 13 introduces no framework-level breaking changes from 12, but PHP 8.3 enforcement means any Alpine or Ubuntu image still on PHP 8.2 will break your pipeline.
  • If using Livewire v3, update to at least v3.6.4 to avoid a critical remote code execution vulnerability (CVE-2025-54068).

Confirm versions with:

php -v          # must show 8.2+ for L12, 8.3+ for L13
php artisan --version
composer show laravel/framework | grep versions

The Five Deployment Paths Compared

Choosing the right deployment path depends on your team's ops expertise, traffic pattern, and budget tolerance for management overhead versus raw infrastructure cost.

PlatformManaged?ScalingCold StartsApprox. Monthly CostBest For
Laravel CloudFully managedAuto (EC2)None (always-on)Free (Starter) / $20+ (Growth)Teams wanting zero ops overhead
Laravel Forge + VPSPartially managedManual / EnvoyerNone$6-24 (droplet) + Forge subscriptionFull server control, predictable billing
Self-managed VPSNoneManualNone$6-30 (DigitalOcean/Hetzner)Maximum control, experienced DevOps teams
Docker (Compose/K8s)None / variesCompose / K8sNoneVaries by hostFull environment reproducibility, CI/CD
Laravel VaporFully managed (Lambda)Auto (scale to zero)100ms–2sUsage-based (can be near-zero)Bursty/background workloads, cost optimisation

Laravel Cloud: Fully Managed EC2 Deployment

Laravel Cloud is a fully managed platform powered by Amazon EC2, launched on 24 February 2025 with Laravel 12. It offers push-to-deploy from Git, automatic scaling, preview environments per branch, and VPC support without SSH.

How Laravel Cloud Works

Laravel Cloud runs applications on always-on EC2 instances, ensuring zero cold starts and predictable response latency. Each environment maps to one or more replicas. The Starter plan is free; Growth plans start at $20/month with usage-based per-replica billing.

Key Cloud behaviors to understand:

  • Deployments are automatic on Git push — no Forge webhook or Envoyer pipeline needed.
  • Worker restarts after deployment are handled by the platform — no manual php artisan queue:restart required.
  • Environment variables are managed via the Cloud dashboard with encryption at rest — never commit .env to version control.
  • Preview environments provide isolated URLs for each pull request — invaluable for code review and stakeholder demos.

Cloud vs. Vapor: The Serverful vs. Serverless Trade-off

Laravel Vapor is ideal for scale-to-zero economics, abstracting Lambda, RDS, ElastiCache, SQS, CloudFront, and Route 53. However, Vapor introduces cold start latency (100ms–2s) and Lambda's execution time limit, making it unsuitable for WebSocket connections or long-running queue jobs. For latency-sensitive APIs or high-concurrency CRUD apps, Laravel Cloud's always-on EC2 containers outperform in latency benchmarks.

Laravel Forge and Laravel VPS: Managed Provisioning, Full Control

Laravel Forge was rebuilt on 1 October 2025, introducing a redesigned dashboard, native zero-downtime deployments, and Laravel VPS — a DigitalOcean-backed product provisioning Ubuntu servers directly from the Forge UI with consolidated billing.

Laravel VPS Explained

Laravel VPS is integrated within Forge. When creating a new server, select Laravel VPS (powered by DigitalOcean), and Forge provisions the droplet, configures Nginx, PHP-FPM, MySQL/PostgreSQL, Redis, and Supervisor, and sets up SSL — all in one workflow. You retain full SSH and root access. PostgreSQL 18 is supported for new server deployments, alongside MySQL.

Zero-Downtime Deployments in Forge

Forge's zero-downtime deployments use an atomic symlink strategy: each deployment clones your code into a timestamped directory inside a releases/ folder, runs all build steps, then atomically switches a current symlink to the new release. Forge retains the last four releases by default, providing instant rollback capability.

Critical configuration steps before enabling zero-downtime in Forge:

  1. List .env and storage/ in the shared paths list — these must persist across releases. Skipping this step results in an empty storage directory and no environment file for each new release.
  2. Forge zero-downtime works on a single server only. For multi-server atomic deployments, pair Forge with Laravel Envoyer — Forge alone cannot coordinate a simultaneous release across multiple servers.
  3. After October 2025, Forge webhook URLs changed. Update any CI/CD pipelines that POST to old Forge deployment trigger endpoints.

Forge vs. Envoyer: When to Use Both

Forge handles server provisioning and single-server deployments. Envoyer handles deploying one project across multiple servers simultaneously with pre-release health checks and traffic cut-over. If your Laravel app runs on two or more servers behind a load balancer, use both: Forge manages each server's configuration, Envoyer orchestrates the coordinated release.

Self-Managed VPS: Nginx + PHP-FPM Production Stack

A self-managed VPS on DigitalOcean, Hetzner, or Vultr offers the lowest hosting cost for steady-state traffic — a 2 vCPU / 4 GB Hetzner CX22 costs around ₹800/month and handles moderate production load. The trade-off is full ops responsibility: OS updates, SSL renewal, firewall rules, and log rotation are your responsibility.

Production Artisan Commands

Run these commands in order on every deployment. Each is a discrete, reversible step — do not combine them into a single script without testing each individually in staging first:

# 1. Cache configuration (reads all config files, writes bootstrap/cache/config.php)
php artisan config:cache

2. Cache routes (writes bootstrap/cache/routes-v7.php)

php artisan route:cache

3. Cache compiled views (writes storage/framework/views/)

php artisan view:cache

4. Cache event-listener map

php artisan event:cache

5. Run migrations (--force bypasses the production environment confirmation prompt)

php artisan migrate --force

Critical warning: After running config:cache, Laravel does not read .env at runtime. Any call to env() outside a config/ file returns null. Always read environment values through config('app.debug'), not env('APP_DEBUG'), in application code.

Nginx Server Block for Laravel

# /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com;
root /var/www/public;
index index.php;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    include fastcgi_params;
}

}

Supervisor for Queue Workers

# /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/storage/logs/worker.log
stopwaitsecs=3600

After updating Supervisor config: supervisorctl reread && supervisorctl update && supervisorctl restart laravel-worker:*

Docker for Laravel: Multi-Stage Production Builds

Docker ensures full environment reproducibility — the same image runs on a developer's laptop, in CI, and in production. The official Docker guide for Laravel is at docs.docker.com/guides/frameworks/laravel/. Multi-stage builds are the recommended production pattern: a builder stage installs Composer dependencies and caches config, while a slim runtime stage copies only the application artifacts.

Multi-Stage Dockerfile for Laravel

# Stage 1: Build
FROM php:8.3-fpm-alpine AS builder
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-interaction
COPY . .
RUN php artisan config:cache 
&& php artisan route:cache
&& php artisan view:cache

Stage 2: Runtime (slim image, no build tools)

FROM php:8.3-fpm-alpine WORKDIR /app COPY --from=builder /app . EXPOSE 9000 CMD ["php-fpm"]

Security rules for Docker in production:

  • Run PHP-FPM and Nginx containers as non-root users — add USER www-data to your Dockerfile.
  • Never bake .env files or secrets into Docker images. Inject them at runtime via Docker secrets, Kubernetes Secrets, or a cloud secrets manager.
  • Use Alpine-based images to minimize the attack surface and image size.
  • Laravel Sail is the official local Docker development environment — keep Sail for development and use the multi-stage Dockerfile above for production. Never use Sail images in production.

Laravel Octane: FrankenPHP, Swoole, and RoadRunner

Laravel Octane (current version v2.17.4) keeps the application framework booted in memory between requests, eliminating the per-request bootstrap overhead that PHP-FPM incurs. In real-world benchmarks, Octane delivers 2.5–3.1x more requests per second than PHP-FPM, and four Octane workers outperform ten PHP-FPM workers under equivalent load.

Choosing an Octane Driver

DriverLanguageHTTP/3?Install ComplexityBest For
FrankenPHPGo (Caddy)YesSingle binaryGreenfield projects, no separate reverse proxy
RoadRunnerGo (binary protocol)NoBinary downloadExisting CI pipelines, typical CRUD apps
SwooleC++ (PHP extension)No (via Nginx)Compile extensionCoroutine concurrency, maximum raw throughput
OpenSwooleC++ (PHP extension)NoCompile extensionCommunity fork of Swoole with additional features

Octane Installation Commands

# Install Octane package
composer require laravel/octane

--- FrankenPHP (recommended for new projects) ---

php artisan octane:install --server=frankenphp php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000

--- RoadRunner ---

php artisan octane:install --server=roadrunner ./rr get-binary php artisan octane:start --server=roadrunner --workers=4

--- Swoole ---

php artisan octane:install --server=swoole php artisan octane:start --server=swoole --workers=4 --task-workers=6

Preventing Memory Leaks in Octane

Octane boots the framework once and reuses the same memory across thousands of requests. Static properties and singleton classes that accumulate state between requests cause memory leaks that are difficult to diagnose. Use lifecycle hooks to reset state explicitly:

use Laravel\Octane\Facades\Octane;

// Runs every 60 seconds across all workers Octane::tick('cleanup', function () { cache()->forget('stale-key'); })->seconds(60);

// In a service provider boot() — resets after each request $this->app->terminating(function () { MyStaticService::reset(); });

Octane's Swoole table cache can reach 2 million cache operations per second — far beyond Redis over a network socket. Use it for hot lookup tables that are safe to share across workers (e.g. read-only config data, feature flags).

For deeper performance tuning beyond the deployment layer, our Laravel performance optimization guide covers query optimization, caching strategies, and profiling tools in detail.

Building a high-traffic Laravel application and unsure whether to use Octane, Cloud, or a self-managed VPS? Our team of web developers in Mumbai will analyze your workload and recommend the right architecture — no guesswork.

Get an Architecture Consultation

Laravel 12 and 13: Deployment-Specific Changes

Laravel 12 introduced native health check routes that expose database, cache, and queue status without any third-party packages. Wire these into your load balancer health probe for automatic instance removal when a dependency fails.

Laravel 13 (March 2026) adds PHP Attributes as an alternative to class properties for model configuration, a stable Laravel AI SDK, a Reverb database driver, Passkeys support, and Cache::touch(). From a deployment perspective, the only action required is confirming your server runs PHP 8.3+ and updating your Docker base images accordingly.

Breaking changes affecting deployment pipelines:

  • Carbon 3.x: Required for Laravel 12. Pin to "^3.0" in composer.json before deploying.
  • PHP 8.2 dropped in L13: Update all Dockerfiles, CI runner images, and server PHP versions before upgrading the framework.
  • Forge webhook URLs changed (October 2025 rebuild): Update CI/CD integrations that call Forge deployment triggers.
  • Octane 2.x: If upgrading from Octane 1.x, read the full UPGRADE.md at github.com/laravel/octane/blob/2.x/UPGRADE.md — worker lifecycle APIs changed.

Security Considerations for Laravel Deployment

Insecure Laravel deployments are an active target. CISA added a Laravel vulnerability to its Known Exploited Vulnerabilities catalog in March 2026 with a mandatory patching deadline of 3 April 2026. The CVEs you must patch before any production deployment in 2025-26 are:

  • CVE-2024-52301 (CVSS 8.7, HIGH): Environment manipulation via crafted query strings when register_argc_argv is enabled in php.ini. Disable this directive in every production PHP configuration and update to a patched Laravel version.
  • CVE-2025-27515: File validation bypass / authentication bypass. Fixed in Laravel 11.44.1 and 12.1.1 — update immediately if on earlier versions.
  • CVE-2024-13918 / CVE-2024-13919: Reflected XSS via debug-mode error pages. Mitigation is straightforward: set APP_DEBUG=false in every production environment. This one CVE alone is why debug mode must never be on in production.
  • CVE-2025-54068: Remote code execution in Livewire v3 up to and including v3.6.3. Update Livewire to v3.6.4+ immediately on any app using Livewire.

For a comprehensive treatment of authentication, authorization, and dependency hardening, read our Laravel security guide.

Additional security hardening checklist for deployment:

  • Confirm APP_KEY is a unique, random 32-character string per environment — sharing keys across environments enables session and cookie forgery.
  • Lock MySQL, Redis, and PostgreSQL ports to internal network only via Forge's firewall UI. Never expose database ports publicly.
  • For Forge servers, configure firewall rules inside the Forge dashboard — not just at the OS level — so rules survive server reprovisioning.
  • For Vapor (Lambda) deployments, use AWS Secrets Manager for sensitive values rather than plain Lambda environment variables.
  • Database migrations must be additive only (backward-compatible) during zero-downtime deployments. The old release symlink remains active for a brief window during the switch — the old codebase must be able to operate against the new schema during that period.

Common Deployment Mistakes and How to Fix Them

Most Laravel production incidents are caused by a small set of repeatable mistakes. Knowing them in advance costs nothing; discovering them at 2 AM during a production outage costs significantly more.

  1. Calling env() in application code: After php artisan config:cache, the .env file is not read at runtime. env('APP_DEBUG') returns null. Always use config('app.debug') instead. Wrap every .env value in a config/ file.
  2. Deploying with dev dependencies: Always run composer install --no-dev --optimize-autoloader. Never deploy a vendor/ directory that includes packages like Faker, PHPUnit, or Laravel Telescope.
  3. Forgetting to restart long-running processes: Octane workers and queue workers hold the old codebase in memory after a deployment. In Forge, trigger a worker reload; in Laravel Cloud this is automatic.
  4. Skipping shared paths in Forge zero-downtime: Without listing .env and storage/ as shared paths, each new release starts with a blank environment and empty storage directory.
  5. Using Forge's atomic deployment for multi-server setups: Forge zero-downtime supports one server only. Add Envoyer for multi-server atomic deployments.
  6. Using Octane without auditing packages: Third-party packages that hold stale references to the request object between Octane requests cause subtle, hard-to-diagnose bugs. Audit every package against the Octane compatibility list before enabling it in production.
  7. Running migrate --force without a staging test: Schema changes causing irreversible data loss are the leading cause of Laravel production disasters. Always test migrations in a staging environment against a production data clone first.
  8. Not pinning Carbon 3.x for Laravel 12: If nesbot/carbon is still at ^2.x in composer.json, the upgrade to Laravel 12 will fail with a dependency conflict during composer install.

Testing and Verifying Your Deployment

A deployment is not complete until it is verified. Run this checklist after every production release:

  1. Visit the application URL and confirm the expected homepage renders without errors.
  2. Check /api/health (or your health check route) — Laravel 12+ exposes database, cache, and queue status by default. All three should return ok.
  3. Confirm APP_DEBUG=false in production by intentionally triggering a 404 — you should see a generic error page, not the Ignition debug screen.
  4. Verify queue workers are running: supervisorctl status should show all laravel-worker processes as RUNNING.
  5. For Octane deployments: php artisan octane:status shows worker health and memory usage per worker.
  6. Run your smoke test suite against the production URL (read-only tests only — no mutations in production).
  7. Check application logs: tail -n 100 storage/logs/laravel.log for any errors logged during the first 60 seconds of traffic.
  8. Confirm Supervisor is restarting failed queue workers: check storage/logs/worker.log for restart events.

Frequently Asked Questions

What is the difference between Laravel Cloud and Laravel Forge?

Laravel Cloud is a fully managed, serverful platform powered by Amazon EC2 that handles all server configuration, scaling, and deployments automatically — you push code and the platform handles the rest. Laravel Forge is a server management panel that provisions and configures VPS servers (including DigitalOcean droplets via the new Laravel VPS integration) while giving you full SSH and root access to the underlying machine. Cloud is ideal for teams that want zero operations overhead; Forge is better when you need custom Nginx configuration, cron job management, or predictable flat-rate monthly billing.

When should I use Laravel Octane instead of PHP-FPM?

Use Laravel Octane when your application needs significantly higher throughput and you can ensure your codebase is stateless between requests. Octane keeps the Laravel framework booted in memory and delivers 2.5–3.1x more requests per second than PHP-FPM in real workloads. However, it requires auditing all third-party packages for Octane compatibility, implementing lifecycle hooks to reset static state, and monitoring memory usage per worker. PHP-FPM is simpler to operate, compatible with all packages, and is the correct default choice for most applications — switch to Octane only when benchmark data shows PHP-FPM is the bottleneck.

How do I achieve zero-downtime deployments with Laravel?

Laravel Forge now enables zero-downtime deployments by default for all new sites using an atomic symlink strategy — each release is deployed to a new timestamped directory, then a symlink switches to the new release instantaneously. For single-server setups, Forge's built-in zero-downtime is sufficient. For multi-server setups behind a load balancer, pair Forge with Laravel Envoyer, which coordinates a simultaneous release across all servers with pre-release health checks. Always list .env and storage/ as shared paths in Forge, and ensure your database migrations are additive-only so the old release can operate against the new schema during the switchover window.

Is Docker the best way to deploy Laravel in production?

Docker is the best choice when environment reproducibility, portability across cloud providers, and CI/CD pipeline integration are your top priorities. A multi-stage Dockerfile using the php:8.3-fpm-alpine base image produces a slim, auditable artifact that runs identically in development, staging, and production. The trade-off is operational complexity: you must manage Dockerfile maintenance, an image registry, and container orchestration (Docker Compose or Kubernetes). Managed platforms like Laravel Cloud and Forge abstract this complexity at the cost of reduced customization and, in some cases, higher monthly spend at scale.

Should I use Laravel Vapor for my Laravel application?

Laravel Vapor is the right choice for workloads with highly variable or bursty traffic patterns where the ability to scale to zero cost during idle periods outweighs the latency cost of Lambda cold starts (100ms–2s per new Lambda container). It is not suitable for applications that require long-running processes such as WebSocket connections (use Laravel Reverb on a traditional server instead), persistent TCP connections, or execution times exceeding Lambda's maximum timeout. For steady-state, latency-sensitive APIs and high-concurrency applications, Laravel Cloud's always-on EC2 containers or Octane on a VPS deliver lower and more predictable response times than Vapor.

Sumeet Shroff
Sumeet Shroff
Sumeet Shroff is the founder of Mumbai Web Designer, a full-service web design and development company based in Andheri West, Mumbai. Over more than a decade building websites for Indian businesses, he has led design and development across Next.js, Laravel, WordPress, and Shopify — the same stack the studio uses today to build fast, lead-generating sites for clients across Mumbai, Andheri, Bandra, Powai, Juhu, and Navi Mumbai. Sumeet's focus is practical rather than decorative: websites that load quickly, rank on Google, and turn visitors into enquiries. His work spans custom website design, ecommerce development, SEO, landing pages, and conversion rate optimisation, and he writes regularly on web design costs, platform choices, and the technical decisions that actually move business results. He founded Mumbai Web Designer to give local businesses an agency partner that stays accountable after launch — with clear contracts, open technology stacks clients fully own, on-page SEO built in from day one, and ongoing maintenance rather than a disappearing act once final payment clears. When advising a business owner, his first questions are always about the goal — leads, sales, bookings, credibility — before a single word about colours or layouts. Sumeet specialises in Next.js, Laravel, WordPress, Shopify, SEO, and UI/UX, and leads the team behind mumbaiwebdesigner.com. Connect with him on LinkedIn to talk web design, development, or SEO for Mumbai businesses.

Comments

Leave a Comment

Loading comments...