The Real Problem
One of our production APIs started becoming painfully slow after the platform crossed 150,000 users. Some API requests were taking more than 4 seconds to respond, causing frontend lag, timeout issues, and poor user experience.
The biggest issue was that everything looked fine in local development, but production traffic exposed major bottlenecks.
This blog explains exactly how we identified the problems and reduced the response time from 4 seconds to under 400ms.
Initial Symptoms
Users started reporting:
- ▸Slow dashboard loading
- ▸Random timeout errors
- ▸Delayed notifications
- ▸Mobile app freezing
- ▸High server CPU usage
At first, we thought the EC2 instance was underpowered, but the real problem was inefficient backend architecture.
Step 1: Profile Every Query
The first thing we did was log all slow queries.
DB::listen(function ($query) {
logger($query->sql, [
'time' => $query->time,
'bindings' => $query->bindings
]);
});
This immediately exposed multiple queries taking over 800ms.
Step 2: Fix the N+1 Query Problem
One endpoint was loading posts and author details separately.
// BAD
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
This generated hundreds of database queries.
We replaced it with eager loading.
// GOOD
$posts = Post::with('author')->get();
Response time instantly improved by almost 40%.
Step 3: Add Missing Database Indexes
We discovered multiple large tables without proper indexing.
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
One report query dropped from 2.3 seconds to 120ms after indexing.
Step 4: Stop Using SELECT *
Several APIs were unnecessarily fetching huge amounts of data.
-- BAD
SELECT * FROM users;
-- GOOD
SELECT id, name, email FROM users;
This reduced memory usage significantly.
Step 5: Introduce Redis Caching
Some dashboard statistics were recalculated on every request.
$stats = Cache::remember('dashboard_stats', 3600, function () {
return DashboardService::generateStats();
});
This removed expensive repeated queries.
Step 6: Move Heavy Tasks to Queues
We found email sending and report generation happening during API requests.
SendInvoiceJob::dispatch($invoice);
Moving these tasks to queues reduced request blocking.
Step 7: Optimize API Resources
Large nested JSON responses were slowing everything down.
We started returning only required fields.
return [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email
];
Smaller payloads improved mobile performance dramatically.
Step 8: Use Pagination Everywhere
One API was returning over 20,000 records.
User::paginate(50);
Simple pagination reduced memory spikes immediately.
Step 9: Add Monitoring
We integrated Laravel Telescope and server monitoring tools.
This helped identify:
- ▸Slow endpoints
- ▸Failed jobs
- ▸Memory leaks
- ▸Excessive API calls
- ▸Queue failures
Production monitoring became one of the most important improvements.
Final Results
After all optimizations:
| Metric | Before | After |
|---|---|---|
| API Response Time | 4.2s | 380ms |
| Database Load | 92% | 38% |
| Failed Requests | High | Very Low |
| CPU Usage | 95% | 45% |
| User Complaints | Frequent | Almost None |
Biggest Lessons Learned
1. Local Performance Means Nothing
Applications behave very differently under production traffic.
2. N+1 Queries Destroy Performance
This is one of the most common Laravel mistakes.
3. Caching Is Mandatory
Without caching, scaling becomes extremely expensive.
4. Monitoring Should Exist From Day One
Most performance issues become visible only after traffic grows.
What I Would Do Differently Today
If I rebuilt the system again, I would:
- ▸Add monitoring earlier
- ▸Use Redis from the beginning
- ▸Design APIs with pagination first
- ▸Audit queries weekly
- ▸Add performance testing before deployment
Final Thoughts
Performance optimization is not about writing clever code.
It is about identifying real bottlenecks using actual production data.
Most scaling problems come from small mistakes repeated thousands of times.
Once we fixed those patterns, the entire platform became faster, cheaper, and more stable.
If you are building Laravel applications expected to grow, start optimizing early before traffic exposes hidden problems.

