PHP 8: Modern PHP Development · Performance and Deployment

Profiling and Caching

Find bottlenecks with profilers and speed up apps with APCu, Redis and HTTP caching.

Measure before optimizing: use Xdebug's profiler, SPX, Blackfire or Tideways to see where time goes, and check database query counts. Common wins: fix N+1 queries, add indexes, cache expensive computations in APCu (per-server, in-memory) or Redis (shared), cache HTTP responses (Cache-Control, ETags, reverse proxies), and move slow work to queues.

<?php
// Cache-aside with PSR-16 (simple cache) backed by Redis
function popularProducts(Psr\SimpleCache\CacheInterface $cache, ProductRepository $repo): array
{
    $key = 'products:popular:v1';
    $cached = $cache->get($key);
    if ($cached !== null) {
        return $cached;
    }
    $products = $repo->popular(limit: 20);
    $cache->set($key, $products, ttl: 300 + random_int(0, 60));   // jitter
    return $products;
}

// APCu for per-server config/derived data
$routes = apcu_entry('routes:v42', fn() => buildRouteTable());

Common pitfalls

  • Leaving Xdebug enabled in production (large slowdown).
  • Caching per-user data under shared keys.
  • Forgetting to version or invalidate cache keys after deploys.

Key points

  • Profile first
  • APCu per server, Redis shared
  • Version keys and add TTL jitter

Further reading: PHP manual: APCu

Practice questions

When would you use APCu instead of Redis?

Answer

For data that's identical on every server and cheap to rebuild (config, route tables), because APCu is in-process and extremely fast. Use Redis when data must be shared across servers or survive restarts.

Why add random jitter to cache TTLs?

Answer

So many keys don't expire simultaneously and trigger a stampede of recomputation against the database.

Open in the app to mark lessons complete, take notes and track your progress.