Updated June 2026. Tested on Laravel 13 and PHP 8.4.
A fresh Laravel deploy can feel sluggish, and the fix is usually not your code. It is that production is still running with development settings, rebuilding things on every request that should be cached once. Here is the checklist I run on every deploy.
Cache the framework
In development Laravel re-reads your config, routes and views on every request so your changes show up instantly. In production you want those compiled once and cached. A single command does all of it.
php artisan optimize
That caches the config, routes, and events together. You can also run them individually if you prefer.
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
One thing to remember: once config:cache has run, the env() helper returns null outside of config files. So make sure you only read environment values through config() in your app code, never env() directly. Re-run these after each deploy, and clear them with php artisan optimize:clear when you need to.
Optimise the autoloader
Install dependencies for production without the dev packages and with an optimised class map.
composer install --no-dev --optimize-autoloader
This builds a single class map so PHP does not scan the filesystem looking for classes.
Enable OPcache
This is the biggest free win and it lives in PHP, not Laravel. OPcache keeps compiled PHP bytecode in memory so it is not recompiled on every request. Turn it on in your PHP config.
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
With validate_timestamps=0, PHP stops checking the disk for changed files, which is faster, but it means you must reload PHP FPM after every deploy for new code to take effect.
Use real drivers for cache, sessions and queues
The file based defaults are fine for local work but slow under load. Point them at Redis in .env.
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
And actually use the queue. Anything slow, sending email, calling an external API, generating a report, should be dispatched to a job and run by a queue worker, so the user's request returns fast instead of waiting.
Cache your own data
Once the framework is fast, look at your app. Cache expensive query results that do not change often.
$popular = Cache::remember('popular-posts', now()->addHour(), function () {
return Post::popular()->limit(10)->get();
});
And watch for N+1 queries, the classic Laravel slowdown, by eager loading relationships with with() instead of letting them load one by one in a loop.
The short version
Run php artisan optimize and composer install --no-dev --optimize-autoloader on deploy, turn on OPcache, move cache, sessions and queues to Redis, and use the queue for slow work. Do those and a Laravel app goes from sluggish to snappy without touching a line of business logic. Questions welcome in the comments.
All comments ()
No comments yet
Be the first to leave a comment on this post.