
September 09, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
You ship a feature locally, run tests, and merge. Then production breaks on a missing .env key, a stale opcache file, or a queue worker still running old code. A repeatable Laravel production deployment checklist closes that gap. It turns release day from guesswork into a short sequence you can run on every project—from a single VPS in Kathmandu to a multi-server stack. This guide covers pre-flight checks, server layout, zero-downtime releases, and post-deploy verification for Laravel applications in production.
What Should Be on Your Laravel Production Deployment Checklist Before You Deploy?
Pre-flight work prevents the failures that only appear after traffic hits the new release. Treat this block as non-negotiable. Skip it once and you will debug at midnight.
Environment and secrets
Production .env must never live in Git. Store it in a shared directory outside release folders when you use symlinked deploys. Confirm these keys at minimum:
APP_ENV=productionandAPP_DEBUG=falseAPP_KEYset and identical across web nodes if you run more than one- Database, Redis, mail, and payment credentials verified against staging
APP_URLmatching the canonical HTTPS domain- Queue and cache drivers pointing at production services, not
syncorfile
On client projects I maintain with Deployer 7 zero-downtime releases, the shared .env sits in /var/www/example.com/shared/.env. Each new release reads the same file. That one detail has prevented more incidents than any fancy tooling.
Version alignment
Match PHP and framework versions before you push. For new Laravel 13 projects, plan on PHP 8.3 or higher. Laravel 12 runs on PHP 8.2+. Many servers I administer still run PHP 8.4 alongside 8.5 during gradual upgrades.
# On the deploy runner and each app server
php -v
composer --version
# In your project
composer install --no-dev --optimize-autoloader --no-interaction
php artisan --version Run composer install with --no-dev on production. Dev packages like Debugbar must never load in prod. Commit composer.lock and deploy that exact lock file.
Database and migration review
Read every pending migration before deploy. Destructive changes need a backup first. Long-running migrations may need a maintenance window or an online schema tool. For reporting-heavy apps, compare PostgreSQL vs MySQL for production before you alter large tables.
How Do You Prepare a Linux Server for Laravel Production?
Application code is only half the stack. The host must run PHP-FPM, a web server, a process supervisor, and scheduled tasks reliably. I deploy most Laravel sites on Ubuntu 22 or 24 with Apache or Nginx fronting PHP-FPM 8.3 or 8.4.
Directory layout for symlink deploys
A typical Deployer layout keeps persistent data outside rotating release folders:
/var/www/example.com/
├── current -> releases/20250909120000/
├── releases/
│ ├── 20250909120000/
│ └── 20250908103000/
└── shared/
├── .env
├── storage/
└── bootstrap/cache/ The web root must point at current/public, not the project root. Pointing at the repo root exposes .env if misconfigured. That mistake still appears on real audits.
Permissions and ownership
PHP-FPM runs as www-data on Ubuntu. Code can belong to the deploy user. Writable paths must belong to the web user or group:
sudo chown -R deploy:www-data /var/www/example.com/shared/storage
sudo chmod -R ug+rwx storage bootstrap/cache After every deploy, confirm new release folders inherit correct ACLs. I have seen uploads fail silently because a fresh release directory lacked group write on storage/app.
Services you must configure
- PHP-FPM pool with opcache enabled and
opcache.validate_timestamps=0in production - Web server vhost with HTTPS, HTTP/2, and security headers
- Supervisor for
queue:workprocesses—see the Laravel queues with Redis production guide - Cron entry:
* * * * * cd /var/www/example.com/current && php artisan schedule:run - Redis 8.x or Memcached 1.6.x for cache and sessions when traffic grows
For full server hardening—firewall, SSL renewal, log rotation—see Linux system administration for production Laravel hosts.
What Are the Exact Deploy Steps in a Laravel Production Deployment Checklist?
Order matters. Running config:cache before migrations, or forgetting to restart workers, leaves production in a split-brain state. Below is the sequence I run on Deployer-managed sites and GitLab CI pipelines—including sister legal-tech portals on shared EC2 infrastructure.
Build phase (CI runner or local)
composer install --no-dev --optimize-autoloader --no-interaction
npm ci
npm run build
php artisan test --parallel Many production servers have no Node.js installed. Build Vite 8.x assets in CI and ship the public/build directory with the release. Committing built assets is boring and effective.
Release phase (on server)
- Clone or rsync code into
releases/TIMESTAMP - Link shared dirs:
storage,.env, sometimesbootstrap/cache - Run
composer install --no-dev --optimize-autoloader - Run
php artisan migrate --force - Run
php artisan config:cache,route:cache,view:cache - Run
php artisan event:cacheif you use it - Atomically swap
currentsymlink to the new release - Reload PHP-FPM to clear opcache
- Restart Supervisor workers:
php artisan queue:restart - Prune old releases—keep three to five
Official guidance lives in the Laravel deployment documentation. Deployer recipes are documented at deployer.org.
Deployer deploy.php essentials
namespace Deployer;
require 'recipe/laravel.php';
set('application', 'example-app');
set('repository', 'git@gitlab.com:org/example.git');
set('deploy_path', '/var/www/example.com');
set('keep_releases', 5);
host('production')
->set('remote_user', 'deploy')
->set('hostname', '203.0.113.10')
->set('branch', 'main');
after('deploy:failed', 'deploy:unlock'); Sites like Adventure Third Pole Trek and several law-firm portals share this Deployer 7 + GitLab CI pattern. One pipeline lint, test, build, and deploy keeps releases predictable for small teams.
| Method | Best for | Downtime | Complexity |
|---|---|---|---|
| Manual FTP/rsync | Legacy fixes only | Minutes | Low |
| Deployer symlink | VPS, single/multi PHP nodes | Near zero | Medium |
| Git pull on server | Internal tools, prototypes | Seconds–minutes | Low |
| Docker / Kubernetes | Scaled API platforms | Zero with rolling updates | High |
For container workflows, read the guide on Dockerizing a Laravel app for production. Most SMB clients in Nepal still land on a well-configured VPS first. That is often the right call on budget.
How Do You Handle Queues, Schedulers, and Background Jobs in Production?
Deploying code does not restart long-lived PHP processes. Queue workers cache the application bootstrap in memory. They keep serving old code until you restart them.
Supervisor configuration
[program:example-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/example.com/current/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopwaitsecs=3600
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/example.com/shared/storage/logs/worker.log After deploy, run php artisan queue:restart. Supervisor respawns workers gracefully. Skipping this step is a classic cause of “fix deployed but emails still broken.”
Scheduler and Horizon
Confirm cron uses the current symlink path—not a hard-coded old release folder. I have fixed production schedulers where cron still pointed at a path from six months ago. Details sit in the Laravel scheduled tasks production setup article.
If you run Laravel Horizon for Redis queues, restart it during deploy the same way you restart standard workers. Treat Horizon as part of the release checklist, not optional tooling.
What Post-Deploy Checks Belong on a Laravel Production Deployment Checklist?
The symlink swap is not the finish line. Run structured verification while you can still roll back quickly.
Automated and manual smoke tests
- HTTP 200 on homepage and one authenticated route
- Login, password reset, and one write action (form submit or API POST)
- Payment or webhook callback in sandbox mode if eCommerce changed
- Queue job dispatch—confirm worker log shows processing
- Scheduled task—check
schedule:listand last run timestamp - Verify
storage/logs/laravel.logshows no new ERROR entries
For payment-heavy apps, validate gateway callbacks after deploy. I've traced failed Khalti and eSewa callbacks to stale route cache more than once. Use the JSON formatter tool to inspect webhook payloads during testing.
Monitoring and safe debugging
Keep APP_DEBUG=false in production always. Use structured logging, external error tracking, and optionally Telescope in restricted environments. Read how to debug Laravel in production safely before enabling any debug UI on live data.
Watch CPU, memory, queue depth, and slow query logs for thirty minutes after release. Performance regressions often appear under real traffic, not during manual clicks.
Security hardening reminders
Confirm HTTPS redirects, HSTS, and that storage and .env are not web-accessible. Review the API security complete checklist when deploy touches Sanctum tokens or OAuth scopes. Rotate keys if credentials leaked during staging tests.
After major releases, run a quick speed optimization pass if response times shifted. Config caching helps, but N+1 queries exposed by new features will not fix themselves.
Hosting, DNS, and SSL
First deploy to a new domain needs correct A/AAAA records and a valid TLS certificate. Let's Encrypt via Certbot on Ubuntu remains my default. For domain and hosting setup on Nepal-based projects, see domain registration and hosting services.
Legal-tech portals such as Court Marriage In Nepal depend on reliable uptime during business hours. A documented checklist helps non-developer staff know when a release is safe to announce.
Key Takeaways
- Run the same ordered steps every release—pre-flight, deploy, verify—so nothing depends on memory.
- Keep
.envandstorage/in a shared directory; never commit secrets or point the vhost at the repo root. - Build frontend assets in CI when the server lacks Node.js 26 LTS; ship
public/buildwith the release. - After symlink swap, reload PHP-FPM and run
queue:restartor workers serve stale code. - Take a database backup before migrations; keep three to five releases for instant rollback via Deployer.
- Smoke-test auth, writes, queues, and webhooks within ten minutes while rollback is still cheap.
People Also Ask
Should I run php artisan config:cache in production?
Yes. Config, route, and view caching cut bootstrap time on every request. Run them after migrations and before or immediately after the symlink swap. If you change .env, rebuild config cache or the app reads stale values. Never run config:cache locally when you need dynamic config during development.
How do I deploy Laravel without downtime?
Use symlink-based releases with Deployer or a similar tool. Build the new release while the old one serves traffic. Run migrations, cache configs, then atomically point the current symlink. Reload PHP-FPM to flush opcache. Users never see a half-updated tree mid-copy.
What PHP version should Laravel production use in 2026?
Laravel 13 requires PHP 8.3 or higher. Laravel 12 supports PHP 8.2+. PHP 8.5 is the current stable line; 8.4 remains widely deployed. Match the same minor version across web nodes and workers. Mixed versions cause subtle serialization and opcache bugs.
Do I need Redis for Laravel production?
Not on day one. File or database drivers work for low-traffic sites. Redis 8.x becomes worth it when you run queue workers, session scaling across nodes, or cache-heavy pages. Most production checklists should at least provision Redis before traffic spikes—especially on eCommerce builds.
Ship Laravel Releases You Can Trust
A written Laravel production deployment checklist turns release anxiety into a ten-minute routine. Start with environment parity and backups. Deploy through symlink releases. Restart workers. Verify logs and critical paths. Keep the checklist in your repo README or runbook so the next developer—or you, six months later—ships with the same discipline.
Need help hardening a live app, setting up Deployer, or migrating from manual FTP deploys? Review the portfolio of production Laravel projects, explore ongoing support and maintenance, or contact us to walk through your stack before the next release.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

