Why is my site slow?

Like most things involving computers, the answer is “it’s complicated.”

Website performance has many factors including your environment, how you’ve built your site, and what sort of traffic it gets.

Craft is a web app, and 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, and 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 at once, you’ll need significant resources to handle the request. Similarly, generating a significant number of simultaneous image transforms will take time and resources.

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/templating/eager-loading-elements

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/3.x/dev/tags.html#when-to-use-cache-tags

This article goes into depth about how the cache tag actually operates: https://nystudio107.com/blog/the-craft-cache-tag-in-depth

To keep the cache tag happy, make sure you don’t have any stalled tasks, either! https://craftcms.com/knowledge-base/resolving-stalled-background-tasks

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 properly, 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 is generating a few hundred queries, that excess execution time adds up to an overall slower request.

Your database server must be properly tuned and have the resources it needs to handle the SQL queries that it receives.

In Craft 2, if you enable devMode, this will output a plethora of profiling and debugging information into craft/storage/runtime/logs as well as to the browser’s console. In Craft 3, you get to use the Debug Toolbar as well as the logs in craft/storage/logs to get this information. All of this information can be used to help debug database performance issues.

In the log files, you’ll see code profiling log entries and executed database queries for the request. Each will have a timestamp you can use to determine what code is holding up the request, and will also point you to the exact line it is located on.

In the browser’s console or the Debug Toolbar, 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 slowest performing 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, and particularly with MySQL, you’ll want to make sure 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 heavier tables, can be the sole cause of slower database performance as its record count grows.

Craft has charset and collation database settings and a db/convert-charset console command to help with MySQL tuning.

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 process of a request. Because of this, plugins can be a potential source of performance issues depending on what they try to do in a request.

To minimize the impact they might have, consider using only plugins absolutely necessary for the site, make sure you’re running the latest versions, and only consider using well-established, tested and actively-developed plugins.

The Load #

Another important 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, PHP 7 vs. PHP 5, etc.)

If you have the option, consider using nginx in place 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 the speed:

Look into output compression to send less data in your web server responses:

Investigate how to use a load balancer to distribute requests equally across multiple web servers.

https://www.nginx.com/resources/glossary/load-balancing/

The Cache #

Smart caching can speed up every part of a site request without any 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

Targeted towards Craft