How we sped up our Laravel API fivefold
Where to start with optimization
Optimization should always start with measurements, not guesses. Before changing any code, we profiled real requests and found that 80% of the response time was spent on database access, not on business logic. So our first target was exactly the work with data.
Fighting the N+1 problem
The most common cause of slow endpoints turned out to be the N+1 problem: for a list of a hundred entities, more than a hundred additional queries to relations were executed. Eager loading via with() reduced this to a few queries.
What exactly we changed
- Added eager loading for all relations used in the response resources.
- Enabled protection against lazy loading in the development environment to catch N+1 at early stages.
- Moved heavy aggregates into separate optimized queries.
Caching hot data
We moved rarely changing reference data and heavy queries into Redis with thought-out event-based invalidation. This removed a significant part of the load from PostgreSQL and stabilized latency under peak traffic.
Resident mode
The final step was running the application in resident mode, which removed the overhead of cold framework initialization on every request. Together, all the measures gave a fivefold speedup of the average response time.
Conclusion
A systematic approach — measure, find the bottleneck, fix it and measure again — allowed us to achieve a multiple speedup without rewriting the application. The main lesson: optimize based on profiling data, not intuition.
Technologies
Tags
Ruslan Ismailov
Senior Web / Backend Developer. Senior web/backend developer with 9 years of experience. Stack: PHP, Laravel, PostgreSQL, Redis, Docker, Kubernetes, REST, microservices, CI/CD. More about me →