What a Laravel app needs in production
Laravel is more than PHP serving requests. A typical production app in 2026 has several processes that all need to run the same release.
- PHP 8.3 or 8.4 with PHP-FPM and OPcache, behind nginx or Caddy
- MySQL, MariaDB or PostgreSQL, and Redis for cache, sessions and queues
- Queue workers, often managed by Horizon, restarted on every deploy
- The scheduler running schedule:run every minute, on exactly one server
- Optional Reverb or another WebSocket server, and Octane for long running workers
- Storage for uploads, either a shared folder or S3-compatible object storage
Any hosting option you pick has to handle all of these, not just the web request. That is where options really differ.
Option one, your own server
You rent a VPS or dedicated server from Hetzner, DigitalOcean, AWS, Vultr, Linode, OVH or another provider, and run the whole stack on it. For most Laravel apps this gives the best price to performance ratio by a wide margin, because you pay the provider's raw compute price with no markup.
- Pros: lowest cost per CPU and GB of RAM, full control over PHP extensions and versions, any region, data stays in your account, no limits on workers or cron
- Cons: you own provisioning, security updates, TLS, deploys, backups and monitoring, unless a tool does it for you
- Fits: production apps with steady traffic, apps with heavy queues, agencies hosting many client apps, teams that want predictable bills
The cons are real if you do everything by hand. They mostly disappear when provisioning and deploys are automated, which is what server management tools exist for.
Option two, a managed platform
Managed platforms run your app for you. Laravel Cloud, Heroku, Render, Railway and similar services take a git repository and handle builds, processes and scaling. You trade money and some control for less operational work.
- Pros: no server to patch, quick start, scaling knobs in a dashboard
- Cons: compute costs more per unit than raw servers, workers and cron often count as separate billable processes, PHP extension and configuration choices are narrower, and moving away later takes work
- Fits: prototypes, apps with very spiky traffic, teams with no one who wants to touch a server
Pricing models differ widely, by process, by usage or by resource, so check each provider's current pricing page and model your own app, including workers, before you decide. Our post on paas vs vps cost walks through that arithmetic for a small team.
Option three, a server panel on your own server
Server panels sit in between. Your app runs on your own server, and a panel provisions it and deploys from git. Laravel Forge is the best known for Laravel and PHP, Ploi and RunCloud are similar with their own focus, and Deployment covers Laravel along with Node.js, Python, Ruby, Go, Java, .NET and Docker. You pay a fixed monthly fee for the panel and the provider's raw price for servers.
- Pros: own server pricing with most of the convenience of a managed platform, no lock-in because servers stay in your cloud account
- Cons: you still choose server sizes and decide when to scale
- Fits: most production Laravel apps, agencies, teams running Laravel next to other stacks
For many teams in 2026 this is the best laravel hosting setup overall, because it combines the economics of option one with most of the comfort of option two.
The production setup that works
Whichever server you choose, the Laravel production setup that holds up looks the same. PHP-FPM serves the app with OPcache enabled and validate_timestamps off, so PHP never checks files on disk during requests.
opcache.enable=1 opcache.memory_consumption=256 opcache.max_accelerated_files=20000 opcache.validate_timestamps=0
With timestamps off, OPcache must be reset on every deploy, which is done by reloading PHP-FPM after the release switch. nginx points the document root at current/public, so the symlink switch moves the whole site at once.
root /home/deploy/app/current/public;
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
}The $realpath_root variable matters with symlinked releases: it resolves the link, so PHP-FPM and OPcache see a new path after each deploy and never mix files from two releases.
A zero downtime Laravel deploy script
A Laravel deploy in a release folder runs composer, builds assets if needed, caches configuration and routes, runs migrations, switches the symlink and reloads processes.
cd "$REL" ln -s /home/deploy/app/shared/.env .env ln -s /home/deploy/app/shared/storage storage composer install --no-dev --optimize-autoloader --no-interaction npm ci && npm run build php artisan config:cache && php artisan route:cache && php artisan view:cache php artisan migrate --force ln -sfn "$REL" /home/deploy/app/current sudo systemctl reload php8.4-fpm php artisan queue:restart
Keep config:cache honest: with a cached configuration, env() calls outside the config folder return null, so read environment values only in config files. Write migrations to be backward compatible, because the old release keeps serving until the switch.
Queues, Horizon and the scheduler
Run Horizon or plain queue workers under supervisor or systemd, and send them a restart signal on every deploy with queue:restart or horizon:terminate so they pick up the new code after finishing current jobs. Add the scheduler as a single cron entry on one server only.
* * * * * cd /home/deploy/app/current && php artisan schedule:run >> /dev/null 2>&1
On multi server setups, mark scheduled tasks with onOneServer and use a shared cache store, so a task never runs twice. If you use Octane, it replaces PHP-FPM for the app and must be reloaded with octane:reload on deploy.
Sizing your first Laravel server
For a typical Laravel app with moderate traffic, a VPS with 2 vCPU and 4 GB of RAM runs PHP-FPM, MySQL or PostgreSQL, Redis and a few queue workers comfortably. Give PHP-FPM a static or ondemand pool sized to memory: divide the RAM you can spare for PHP by the average memory of one worker, usually 40 to 80 MB, and leave room for the database. Watch for "server reached pm.max_children" in the FPM log, which means requests are queuing. When the database grows or queues get heavy, move the database to its own server first. That one split usually buys more headroom than doubling the app server.
How to choose the best laravel hosting for your team
Use a short decision path. If you have no one willing to own a server and traffic is unpredictable, start on a managed platform and model the cost of your workers. If you run steady production traffic, several apps or heavy queues, put Laravel on your own servers and use a panel so provisioning, deploys and backups are not manual. If your team also ships Node.js, Python or other stacks, pick a panel that handles all of them, so you do not run two tools side by side.
How Deployment hosts Laravel on your servers
Deployment provisions your own server for Laravel with PHP 8.3 or 8.4, PHP-FPM tuned with OPcache, nginx or Caddy, MySQL, MariaDB or PostgreSQL and Redis, plus a firewall, SSH hardening and security updates. Each push to your branch builds in a new release folder, runs your editable deploy script with composer, asset builds, caches and migrations, checks a health URL and switches the symlink for zero downtime, then reloads PHP-FPM and restarts Horizon or queue workers. The scheduler runs as a managed cron job with logs, Let's Encrypt certificates renew on their own, and backups go to your own S3-compatible storage. See the laravel hosting page for the full stack, compare us honestly on the laravel forge alternative page, or paste your repository into the demo on the home page to see your deploy plan.