Most PHP performance advice is either obvious ("use the latest PHP version") or irrelevant to real projects ("rewrite everything in Swoole"). After 7+ years of building and rescuing PHP applications β from WordPress sites choking on shared hosting to Laravel apps handling thousands of daily users β these are the seven optimizations that consistently deliver measurable improvements. Every one of them comes from a real project, with real before-and-after numbers.
1. Turn On and Tune OPcache
OPcache compiles your PHP scripts once and keeps the compiled bytecode in memory, so every subsequent request skips parsing and compilation entirely. It ships with PHP and is often enabled β but rarely tuned. On a client's WooCommerce store, properly configuring OPcache cut average response time from 480ms to 290ms without touching a line of application code.
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; production only β redeploys must reset OPcache
The setting most people miss is validate_timestamps. With it disabled, PHP never stats the filesystem to check whether files changed β a meaningful saving on busy sites. Just remember to reload PHP-FPM on every deployment.
2. Kill N+1 Queries with Eager Loading
The single most common performance bug I find in code audits: loading a list of records, then running one additional query per record inside a loop. Fifty blog posts with authors and categories becomes 101 queries. In Laravel, the fix is one method call:
// 101 queries
$posts = Post::latest()->take(50)->get();
// 3 queries
$posts = Post::with(['author', 'category'])->latest()->take(50)->get();
In WordPress, the same disease appears as get_post_meta() calls inside loops β use update_post_meta_cache() or fetch what you need in the main query. On one Laravel dashboard I audited, fixing three N+1 hotspots dropped page generation from 2.1 seconds to 340ms.
3. Add the Database Indexes You're Missing
Any column that appears in a WHERE, JOIN, or ORDER BY on a large table needs an index. It sounds basic, and yet almost every slow application I inherit is missing at least one critical index. Run your slowest query through EXPLAIN: if you see a full table scan on a table with 100k+ rows, that is your problem.
One client's order lookup took 6 seconds at 800k rows. A single composite index on (customer_id, created_at) brought it to 45 milliseconds. No code change β one migration.
4. Cache Expensive Work, Not Everything
Caching everything blindly creates stale-data bugs. Caching the right things transforms performance. Good candidates: aggregated counts, external API responses, rendered menus and widgets, settings lookups, and anything that touches more than a few tables to compute. In Laravel, Cache::remember() makes the pattern trivial:
$stats = Cache::remember('dashboard.stats', 600, fn () => [
'orders' => Order::whereMonth('created_at', now()->month)->count(),
'revenue' => Order::whereMonth('created_at', now()->month)->sum('total'),
]);
Use Redis or Memcached in production β the file cache driver adds disk I/O exactly where you are trying to remove it.
5. Move Slow Work Out of the Request
Sending an email, generating a PDF, resizing an image, calling a third-party API β none of it belongs in the request that a human is waiting on. Queue it. Laravel's queue system with a database or Redis driver takes minutes to set up, and the perceived speed win is enormous: a checkout that fired three emails and a webhook synchronously went from 3.5 seconds to 400ms after I queued the lot.
6. Upgrade PHP β the Boring Tip That Beats Most Clever Ones
PHP 8.3 runs typical real-world code 2β3Γ faster than PHP 7.2, with lower memory usage. If your application still runs on an EOL PHP version, upgrading is likely the highest-impact hour you can spend β and it comes with security patches you are currently missing. Test on staging, fix the handful of deprecations, and collect the free performance.
7. Measure Before You Optimize
Every tip above came from measuring, not guessing. Before changing anything, find out where the time actually goes: Laravel Telescope or Debugbar for query timing, EXPLAIN for the database, Xdebug profiles or simple microtime() checkpoints for PHP itself. Optimizing code that accounts for 2% of response time is wasted effort β profilers stop you from doing it.
Bonus: the Settings Nobody Tunes
Two lower-level wins that show up on almost every audit. First, the realpath cache: PHP resolves file paths on every include, and frameworks include hundreds of files per request. The default cache is tiny for a modern Laravel or WordPress install:
realpath_cache_size=4096K
realpath_cache_ttl=600
Second, a JIT reality check: PHP's JIT compiler makes headlines, but for typical I/O-bound web workloads β database queries, template rendering, API calls β it changes almost nothing, because your bottleneck is not CPU-bound PHP execution. Enable it if you run heavy computation in PHP; do not expect it to fix a slow WooCommerce checkout.
While you are in the config, check memory_limit against reality. I regularly find shared hosts running WordPress at 128M with 40 plugins, causing silent fatal errors under load that look like random white screens. Measure peak usage with memory_get_peak_usage() and set the limit with headroom, not superstition.
Don't Forget the Layer Above PHP
The fastest PHP request is the one that never reaches PHP. Full-page caching β via nginx FastCGI cache, Varnish, or a well-configured caching plugin on WordPress β serves anonymous traffic in single-digit milliseconds regardless of how heavy the underlying code is. On one content site, enabling FastCGI cache for logged-out visitors took the server from struggling at 30 requests/second to comfortably absorbing 800.
Pair it with sane HTTP caching headers for static assets (Cache-Control: max-age=31536000, immutable on fingerprinted CSS/JS) and a CDN for images, and the origin server ends up doing only the work that genuinely requires PHP: logged-in pages, carts, checkouts, and APIs. This is also the cheapest scalability you will ever buy β a $10 VPS with proper caching outperforms a $100 server without it.
One caveat from production experience: cache invalidation is where full-page caching bites. Test that publishing a post, updating a price, or changing a menu actually purges the affected pages. A stale price on a cached product page is a customer-support fire, not a performance win.
The Takeaway
Fast PHP applications are not built with exotic tricks. They are built by enabling OPcache, eliminating N+1 queries, indexing the database properly, caching expensive computations, queueing slow work, and running a modern PHP version β in roughly that order of effort-to-impact. If your site or application feels slow and you want a professional set of eyes on it, that diagnostic work is exactly what I do as part of my web development services β from quick audits to full performance rebuilds.
Related Service
π» Web Development
Custom websites and web applications built with PHP, Laravel, WordPress, and React β fast, secure, scalable, and tailored to your business goals.
Explore Web Development →