Drupal Performance Checklist
Performance work should begin with measurement and cache correctness. A fast uncached request is useful; a correctly cached request that never repeats expensive work is better.
Verify the cache layers
Confirm Internal Page Cache, Dynamic Page Cache, and render caching are enabled and effective. BigPipe improves perceived performance for pages containing uncacheable placeholders. Audit cache contexts before adding broad max-age exceptions.
Control the payload
Aggregate and compress assets in production, remove unused libraries, use responsive image styles, set intrinsic image dimensions, and lazy-load below-the-fold media. A CDN helps only after cache headers and invalidation are correct.
Measure the backend
Inspect slow queries, indexes, external calls, queue work, and PHP profiling. Move non-interactive work out of the request, but keep queue jobs observable and idempotent.
Measure a request before optimizing it
Start by separating backend response time from frontend rendering time. A slow page can be caused by PHP execution, database queries, remote services, oversized images, blocking JavaScript, layout shifts, or a cache miss that should have been a hit. Each cause requires a different tool and a different fix.
Record a baseline before changing anything. Compare anonymous and authenticated requests, first and repeated requests, and representative pages rather than only the home page. Performance improvements are much easier to trust when the same measurement is repeated afterward.
Cache correctness comes before cache volume
A component that varies by user or route needs the proper cache context. A listing that changes when content is created or updated needs appropriate cache tags. Disabling caching because stale output appeared may hide the bug while making every request more expensive.
When a page is unexpectedly uncacheable, trace which child introduced the low max-age instead of immediately accepting the entire page as dynamic.
Move expensive work away from the request
Search indexing, synchronization, large exports, remote notifications, and other non-interactive work are good candidates for queues or scheduled processing. Interactive requests should do the work necessary to answer the user, not every follow-up task caused by that action.
Background work still needs limits, retries, logging, and monitoring. Moving code to a queue changes when the cost is paid; it does not make that cost disappear.
Key Takeaways
- Measure before and after every optimization.
- Fix cache metadata instead of disabling caches.
- Optimize images and asset delivery alongside PHP.