Why Your Laravel App Is Slow (And How to Actually Fix It)
At some point, every Laravel app hits that moment.
Pages feel sticky.
API responses take just a little too long.
You open Chrome DevTools and watch requests… linger.
Your first instinct is usually the wrong one.
You don’t need Redis everywhere.
You don’t need to rewrite things in Go.
You probably don’t even need to “optimize” yet.
Most slow Laravel apps aren’t slow because Laravel is slow.
They’re slow because of a handful of common mistakes that quietly pile up over time.
Let’s walk through the real reasons Laravel apps drag, and what actually fixes them.
1. The Silent Killer: N+1 Queries
If your app feels fine locally but crawls in production, this is often the culprit.
The symptom
- One page loads dozens or hundreds of SQL queries
- Database time dominates your request timeline
- Everything gets worse as data grows
The cause
You load relationships lazily without realizing it.
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
That looks harmless.
It isn’t.
Laravel runs:
- 1 query for posts
- 1 query per author
That’s N+1 queries.
The fix
Use eager loading. Always.
$posts = Post::with('author')->get();
This single change can drop page load times from seconds to milliseconds.
Rule of thumb
If you loop and touch a relationship inside the loop, eager load it.
2. You’re Doing Work That Doesn’t Belong in a Request
HTTP requests should be fast and boring.
If your controller:
- Sends emails
- Generates PDFs
- Processes images
- Calls external APIs
- Syncs data
…you’re slowing every user down.
The fix
Queues.
Laravel queues exist to move slow work out of the request lifecycle.
SendWelcomeEmail::dispatch($user);
Instead of:
Mail::to($user)->send(new WelcomeEmail());
Now your response returns immediately, and the heavy lifting happens in the background.
Bonus
Queues also make your app more reliable.
If something fails, it retries. Requests don’t.
3. You’re Hitting the Database Way Too Often
Databases are fast.
They’re just not free.
If you:
- Load the same settings on every request
- Recalculate counts constantly
- Query reference data that barely changes
You’re wasting time.
The fix
Cache things that don’t change often.
$settings = Cache::remember('settings', 3600, function () {
return Settings::first();
});
Caching isn’t about guessing.
It’s about recognizing repeat work and stopping it.
Good caching candidates
- App configuration
- Feature flags
- Permissions
- Dashboard aggregates
- Expensive API responses
4. You Forgot to Turn On the Free Speed Boosts
Laravel ships with performance features people forget to enable.
In production, you should be running:
php artisan config:cache
php artisan route:cache
php artisan view:cache
Without these:
- Config files are parsed every request
- Routes are rebuilt constantly
- Blade templates compile on demand
These commands cost nothing and save real time.
Important
Never cache config or routes in local development unless you know why you’re doing it.
5. Your App Is “Fast” but Your Queries Aren’t
Sometimes Laravel isn’t the problem.
Your SQL is.
Watch for:
- Missing indexes
- Large
WHERE INclauses - Sorting huge datasets in PHP instead of SQL
- Pulling entire tables when you only need counts
Tools that help
- Laravel Debugbar
- Telescope
- Database slow query logs
If a query takes 300ms, caching won’t save you.
Fix the query.
6. Horizon Isn’t Optional Once You Use Queues Seriously
If you’re using Redis queues in production and not running Horizon, you’re flying blind.
Horizon gives you:
- Queue throughput visibility
- Failed job tracking
- Worker scaling control
- Real insight into background performance
Queues are infrastructure.
Horizon is the dashboard.
7. The Hard Truth: Most “Optimizations” Are Guesswork
The biggest mistake developers make is optimizing without measuring.
Before changing anything, ask:
- Is this database time, PHP time, or network time?
- Is the delay consistent or spiky?
- Does it scale with data size?
Laravel gives you the tools.
Use them before reaching for “clever” fixes.
A Simple Performance Checklist
If your Laravel app feels slow, start here:
- [ ] Check for N+1 queries
- [ ] Move slow tasks to queues
- [ ] Cache repeat work
- [ ] Enable config, route, and view caching
- [ ] Inspect slow SQL
- [ ] Monitor queues with Horizon
Do these well, and most performance problems disappear.
Coming Next (This Will Be a Series)
Each of these topics deserves a deeper dive.
In future posts, we’ll break down:
- Debugging N+1s like a pro
- Designing cache layers that don’t lie
- Queue architecture that scales cleanly
- When Laravel is fast enough — and when it isn’t
Laravel isn’t slow.
Unexamined apps are.
Member discussion