Measure first
How to speed up a slow PHP/Symfony application
Do not guess what is slow. Find one bottleneck, fix it, and measure the result again.
First, the short version
Why is an application slow?
The slowness is often not caused by PHP itself. It may come from one unnecessary SQL query, a remote API, or work repeated on every page load.
Start with one URL and the same scenario. The Symfony profiler shows time, queries, and other calls. In production, use safe monitoring — not a public debug panel.
Get ready
What you need
Measure before and after the change. Otherwise you cannot know whether it really helped.
- One slow page or API request you can repeat with the same data.
- A development environment with the Symfony profiler or safely configured application monitoring in production.
- Access to slow SQL queries and their execution plans.
- A way to clear and inspect cache, so you do not accidentally measure an old result.
Step 1
Look for the cause in this order
Do not make ten optimizations at once. Each step needs a measurable reason.
1. Measure a specific request
- Open the same page several times. The first load can be affected by cache warm-up, so record more than one measurement.
- In the profiler, look at total time, the number of database queries, and slow external calls.
- Choose one most expensive part. Only then change code.
php bin/console about Symfony profiler 2. Fix the database query
- Find repeated queries and loading data one record at a time. This is often the N+1 problem.
- Run a plan for the specific SQL query. Add a database index only when it matches filters and sorting you actually use.
- After the change, compare time and the number of rows read. Indexes also have a cost on writes.
EXPLAIN SELECT ...; PostgreSQL: EXPLAIN 3. Cache repeated work
- Use cache for an expensive calculation or data that does not change for a while. Do not cache all personalized content without thinking.
- For shared cache, you can use Redis. The key must distinguish language, user, or filter when they change the result.
- When source data changes, clear the related cache intentionally. This is called cache invalidation.
php bin/console cache:pool:list Symfony Cache Step 2
Check that the right part is faster
A faster number is not enough. The result must stay correct for a regular user.
-
Repeat the same measurement
Compare several loads of the same page. Record the time before and after the change.
-
Check queries
In the profiler, confirm fewer queries or a better plan. An index that is not actually used does not solve the problem.
EXPLAIN ANALYZE SELECT ...; -
Test behavior without cache
Clear the cache, change data, and open the page again. A user must not receive stale or someone else’s content.
php bin/console cache:pool:clear cache.app
If something goes wrong
Common problems
I added cache and the page is still slow
Check whether a cache hit ever occurs. You may have a different key every time, a very short lifetime, or slow code before the cache.
The new index did not help
Look at the plan with EXPLAIN. The query may filter another column, return most of the table, or need a different SQL shape.
I enable the profiler for everyone in production
Do not do that. The profiler can expose sensitive data and adds overhead. Use limited monitoring with access only for the team.
Old data appears after optimization
Add a clear cache invalidation rule. Clear only keys related to the change, not everything blindly on every write.
Done
The application has less work to do.
You now have a repeatable process: measure, find the bottleneck, change one thing, and check the result.