Troubleshooting Performance Issues
Website performance has many factors, including your environment, how you’ve built your site, and the type of traffic it gets.
Craft is a web app; fine-tuning it is similar to any PHP-based, database-backed application. This article covers the main areas to investigate and points to further resources on modern web application performance.
The Templates #
Craft is a flexible CMS that doesn’t put many constraints on your content architecture. Site developers have complete control over front-end HTML output. Because of this, Craft will do whatever your templates tell it to do, which can be a common bottleneck for performance.
For example, if you’re executing a million queries or displaying a million entries simultaneously, you’ll need significant resources to handle the request. Similarly, generating many simultaneous image transforms will take time and resources.
Frequently using the {{ svg() }}
template function without caching its output, could slow template rendering, especially if SVG files are loaded from remote Asset Volumes or URLs.
You might want to start with common template performance “gotchas” to avoid with Craft: https://craftcms.stackexchange.com/questions/59/what-are-the-most-common-template-performance-gotchas-to-avoid
If you’re running into the dreaded N+1 SQL database query problem in your templates, you should be taking advantage of Craft’s eager loading support: https://craftcms.com/docs/4.x/dev/eager-loading-elements.html
Craft’s {% cache %}
template tag is another tool in your quest to tame the performance dragon.
It’s also good to know when to use the cache tag and when not to: https://craftcms.com/docs/4.x/dev/tags.html#when-to-use-cache-tags
This article goes into depth about how the cache tag operates: https://nystudio107.com/blog/the-craft-cache-tag-in-depth
To keep the cache tag happy, ensure you don’t have any failed queue jobs, either! https://craftcms.com/knowledge-base/resolving-failed-queue-jobs
The Database #
In a poorly-configured database server, database queries aren’t going to execute as fast as they could in an optimized environment. If your database is configured correctly but doesn’t have enough resources assigned to it to handle the load of your site (common in shared hosting environments), you can run into the same execution time issues. If a web request generates a few hundred queries, that excess execution time adds to an overall slower request.
Your database server must be properly tuned and have the necessary resources to handle the SQL queries it receives.
Enabling devMode will output a plethora of profiling and debugging information into Craft’s storage/logs
folder. You can also use the Debug Toolbar to display additional information useful for debugging in the browser.
For example, you’ll see database profiling output for the request, including the number of queries executed, their execution times, and the SQL for those queries. These are sorted in ascending order, with the slowest-performing ones at the top.
Try running one of Craft’s queries directly with a database client. If the response is still slow after bypassing Craft/PHP, you’ve narrowed the issue to database performance.
Often, particularly with MySQL, you’ll want to ensure your character_set
and collation
values are consistent across the database since you may have first installed Craft in an environment whose encoding defaults differ from production. Mismatched encodings and missing indexes, especially in larger tables, can be a large part of slower database performance as its record count grows.
The Plugins #
Craft’s flexible templates and content architecture can be further complicated by plugins that can get involved at nearly every step in the request process. Because of this, plugins can be a potential source of performance issues depending on what they try to do in a request.
To minimize their impact, consider using only plugins necessary for the site, ensure you’re running the latest versions, and only consider using well-established, tested, and actively-developed plugins.
The Load #
Another vital thing to determine is when the slowdown occurs.
- Can you reproduce it on every single request?
- Does it only happen when your site gets hit with traffic?
- How much traffic does it take?
- Does it happen at a specific time of the day, every day, or only on Tuesday?
There are plenty of commercial and free load testing tools you can use to help identify load issues in staging and development before you go live.
The Environment #
Make sure your webserver(s), database, network, disk drives, load balancers, routers, etc., are all properly tuned and have enough resources to handle the traffic your site is expecting. If you don’t have much control over the environment, make sure you’ve chosen a good host that knows what they’re doing.
Run the latest version of PHP you can. It’s low-hanging performance fruit because newer versions typically run faster and consume less memory. This is especially true for major versions (PHP 8 vs. PHP 7)
If you have the option, consider using nginx instead of (or in front of) Apache. It handles high concurrency much better than Apache and with fewer resources: https://help.dreamhost.com/hc/en-us/articles/215945987-Web-server-performance-comparison
There are other practical things to consider when deciding Apache vs. nginx, too: https://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations
Consider going all in on https and http2, not just for privacy but for speed:
Look into output compression to send less data in your web server responses:
Investigate how to use a load balancer to distribute requests across multiple web servers equally.
https://www.nginx.com/resources/glossary/load-balancing/
The Cache #
Smart caching can speed up every part of a site request without noticeable differences for content authors or visitors.
Whether it’s something like Varnish that acts as a caching HTTP reverse proxy or through services like Cloudflare, or any of the other numerous CDN services around the world, they can all speed up requests to your site.
At the web server level, you can enable PHP byte-caching extensions like Opcache or pick your favorite flavor of PHP caching extensions.
Your templates should take advantage of browser caching for their resources.
For a better understanding of the different caching options available in a Craft installation, see: https://craftcms.stackexchange.com/a/13383/57
Additional Resources #
General website performance
- developers.google.com/web/fundamentals/performance/
- developers.google.com/speed/docs/insights/rules
- developer.yahoo.com/performance/rules.html
- kinsta.com/learn/page-speed/
- nystudio107.com/blog/a-pretty-website-isnt-enough
Targeted towards Craft
- Things to know about fast Craft CMS websites
- nystudio107.com/blog/frontend-dev-best-practices-for-2017
- nystudio107.com/blog/image-optimization-project-results and nystudio107.com/blog/creating-optimized-images-in-craft-cms
- nystudio107.com/blog/implementing-critical-css
- onedesigncompany.com/news/high-performance-craft-caching-with-fastly
- supercool.github.io/2015/06/08/making-craft-sing-with-varnish-and-nginx.html
- patpohler.com/performance-optimization-craft-cms/