The first time I deployed a Laravel app to production, I just uploaded the files and called it done. The app worked, but it was noticeably slower than it should have been. I had skipped all the production optimizations.
Here is what I do now on every deployment.
Cache everything Laravel can cache
Laravel parses your config files, routes, and views on every request — unless you cache them. In production, always cache:
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cacheThese commands create optimized files that Laravel reads directly, skipping the parsing step. The difference is measurable.
Important: run these after every deployment, not just once.
Optimize Composer's autoloader
composer install --optimize-autoloader --no-devThe --optimize-autoloader flag generates a class map so PHP can find classes without scanning directories. The --no-dev flag removes development packages that should not be on production.
Set the right environment variables
This one is critical for security:
APP_ENV=production
APP_DEBUG=falseWith APP_DEBUG=true, Laravel shows detailed error pages with stack traces, file paths, and environment variables. That is a serious security risk in production. Always set it to false.
Use a process manager for queue workers
Queue workers die sometimes — out of memory, unhandled exceptions, server restarts. Supervisor keeps them running:
[program:laravel-worker]
command=php /var/www/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=trueThe --max-time=3600 flag restarts the worker every hour, which prevents memory leaks from accumulating.
Enable PHP OPcache
OPcache compiles your PHP files once and stores the compiled bytecode in memory. Subsequent requests use the cached bytecode instead of re-parsing the PHP files.
Most hosting providers enable this by default. If yours does not, add to php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0Setting validate_timestamps=0 means OPcache never checks if files have changed. This is fine in production where files only change during deployments. Just clear the OPcache after each deployment.
Add database indexes
Before going live, run your most common queries through EXPLAIN and make sure they are using indexes. A missing index on a column you filter by frequently can make queries 100x slower.
Set up monitoring
You need to know when things go wrong before your users tell you. At minimum:
- Set up error tracking (Sentry has a free tier)
- Set up uptime monitoring (UptimeRobot is free)
- Configure Laravel's log channel to send critical errors somewhere you will see them
Deployment is not the end. Monitoring is what keeps production healthy.




