FacetWP performance, speed, limits and scalability
We often get questions about FacetWP’s scalability and limitations, the speed of indexing, filtering and search, and hohttps://facetwp.com/help-center/developers/facetwp-performance-speed-limits-and-scalability/ to fix slow page loads or slow filtering.
Below we will go into all the different factors that can be at play for indexing, filtering and search:
A lot of factors weigh into the time it takes FacetWP to index your content. Besides the number of posts, custom fields and terms/categories, other factors are the number of facets and types of the facets being indexed, the server specs, etc.
As a general guideline, on average indexing may take about a 700-1000 records per minute for indexing WooCommerce products with variants.
We’ve been tweaking FacetWP’s database index table over the years, and its current form is as efficient as it can get with MySQL. Keep in mind that MySQL is a general-purpose database so in terms of performance it’s not going to compare well with dedicated search solutions like Elasticsearch or Algolia.
The best case maximum limit of FacetWP would probably be somewhere in the hundreds of thousands of posts. We’ve had a customer successfully testing the plugin with 500K+ results, but the reliable maximum depends a lot on the server specs and the other factors mentioned above.
When reading these numbers be aware that if you are using WooCommerce product variations, the number of indexed posts will be a lot higher than you’d guess. Each variation is a separate item that needs to be indexed, so the true count will be much higher than the number of products.
When indexing facets into its
wp_facetwp_index table, FacetWP uses the following limits:
|The facet’s technical name. The name is also visible in the URL when the facet has active selections.
|The facet choice’s technical value, see explanation below.
|The facet choice’s display value, see explanation below.
|The maximum post ID. See below for an explanation, and how to increase this number.
|The maximum number of facet choices in facets with a “Count” setting, even if it is set to
-1 (unlimited). This applies to the following facet types: Checkboxes, Dropdown, Radio, fSelect, Hierarchy, and Color facets.
|The maximum number of term levels indexed when a facet uses a hierarchical taxonomy as data source.
FacetWP indexes two values for each facet choice. The
facetwp_value is a facet choice’s technical value. It can be seen in the URL when the choice is selected. The
facetwp_display_value is the choice’s label as displayed in the facet itself.
Depending on the data source of the facet, and the value itself, these two values can be the same or different. For simple custom fields they are the same. But for example for taxonomy terms they are different: term slugs are indexed as
facetwp_value, and term names as
Also, depending on the presence of special characters, the
facetwp_value value can be hashed for security reasons.
INT unsigned as the SQL data type for the
post_id column in the
wp_facetwp_index table. This SQL data type can contain 8-byte integer data, which means the highest post ID that can be indexed is
Believe it or not, in our support we regularly encounter users with post IDs higher than this. If that happens, those posts will not be indexed properly, which will lead to empty facets or facets with choices missing, depending on if all or some post IDs are above this limit.
Fortunately, there is an easy fix. Add the following code to your (child) theme’s functions.php to change the data type for the
post_id column from
INT unsigned to
add_filter( 'facetwp_use_bigint', '__return_true' );
BIGINT unsigned data type can hold integers up to
2^64-1), which should be enough even in the most extreme scenarios.
After adding the above code, make sure to re-create the indexing table by purging it first, and then performing a full-re-index, by clicking the red “Re-index” button.
If you have a very large site and the indexer is stalling, make sure to check your web server’s PHP error log for clues. The most common cause is the server running out of memory. See the Indexing page for all other common indexing issues.
If you are hosting your website on the WP Engine platform and you are experience problems with the indexer stalling or not indexing all your posts, be aware that WP Engine is limiting long queries (longer than 1024 characters) for performance reasons. The following line in wp-config.php will prevent that:
define( 'WPE_GOVERNOR', false );
If your site has a lot of content that changes often, FacetWP’s automatic indexing can become problematic. In this case using WP-CLI to programmatically trigger re-indexing at pre-defined moments is the recommended approach. If you go for indexing with WP-CLI, it is recommended to turn off automatic indexing, with the facetwp_indexer_is_enabled hook.
FacetWP was built with performance in mind and is very fast itself. We’ve structured and highly optimized our data storage and have analyzed every query to make sure that it runs as efficiently as possible.
So ultimately, FacetWP’s speed depends on your server, the theme setup, your plugins, and the amount of content. If your server is overloaded (i.e. too many heavy plugins or other users) or underpowered (too little memory or CPU power), then obviously FacetWP will not run at its peak.
Check out our tutorial on how to make your website faster, that covers many of these subjects.
To understand where slowness on your listing page may come from, keep in mind that FacetWP can be only as fast as your uncached site. This is because FacetWP uses AJAX requests to refresh the facets and results listing. WordPress AJAX requests aren’t cached by default and require all of WordPress to load. FacetWP uses WP’s
init hook to ensure that WP (and all other plugins) are loaded. Otherwise, no integrations would work, post types wouldn’t be registered, etc. This means that if it takes three seconds for the initial unfiltered (uncached) page to load, then it will also take three seconds for a filtered AJAX request.
If you see filtering being slower than the initial (or other) cached page loads, it’s tempting to come to the conclusion that slow filtering or pagination is caused by FacetWP. Although possible, this is very unlikely. Most often it is due to (a combination of) server performance, inefficient listing templates or loop code with large amounts of queries to render each post, the amount of content, or other plugins slowing the AJAX request. Even on a fast server, FacetWP can only be as fast as the slowest plugin on your site.
Certain types of caching can help to speed things up, but if you don’t resolve the underlying issues, you are just sweeping all inefficiencies “under the rug” and they will keep slowing down each AJAX request.
The best course of action if you want to speed up your page and facet filtering is to first (temporarily) disable all caching, and start analyzing your true (uncached) page load times and queries to find out where the slowness is coming from. The recommended tool to do this is the free Query Monitor plugin.
Check out our tutorial about how you can use Query Monitor to optimize performance by reducing the total query time and the number of queries on your page, optimizing the code of your listing template and loops, profiling your plugins, and optimizing your server setup.
A lot of performance can usually be gained by profiling the plugins you are using, de-activating unnecessary or heavy plugins, and making sure the remaining ones work well together. Also make sure to de-activate any plugins you are not continuously using, like WP All Import, database optimization plugins, and Query Monitor itself.
Besides caching and optimizing your queries, the list of things you can do to speed up your website and page loads is near endless. Check out our separate tutorial on improving page load speed to give you an overview and get you started.
Also consider using FacetWP’s built-in Listing Builder for your post listing/grid. On WP archive pages, FacetWP makes a custom AJAX request to the same page URL, but the Listing Builder uses its own REST API endpoint, which is faster. It also loads less HTML in its AJAX call than FacetWP does on a WP archive (see below).
If you want page load times in the ~1s range, the best approach would be to code your own theme and listing archive with as little overhead as possible. Or maybe start with a skeleton theme of some sort, then use our FacetWP’s built-in Listing Builder for your listing template.
After optimizing your theme, plugins, and server specs to speed up page load times, there are a few things you can do to speed up the filtering itself.
Factors that influence filtering speed include:
- the listing template itself (how efficient is the loop and display of each result):
- the number of active facets on the page
- the facet types in use
- caching of FacetWP’s AJAX requests
Using a Listing Builder template is usually faster than using FacetWP on WP archive pages or with a custom query. The Listing Builder is optimized to makes as few SQL queries as possible. On WP archive queries, FacetWP has to load all HTML within the page’s
To get accurate facet counts, FacetWP needs to use the unpaginated query. So you could consider reducing the total number of results in your listing query. If you have a lot of content, you could split it up into different listings/archives, or offer content in separate category/term archive pages.
Try to minimize the number of posts per page in your listing to something reasonable, like 16-20 posts. This will reduce the number of queries needed to load the data for all displayed posts.
Minimize the number of queries needed to display all information for a post. Even if you have only one unnecessary query taking only milliseconds, because of the number of times it runs (the number of posts per page) it can have a – sometimes huge – negative impact on the resulting total query time, especially if your number of posts per page is high.
Each facet will slow down the page slightly because the choices have to be queried and calculated. We’ve seen users with an enormous amount of facets on a page. Try to limit the amount by going with a few well-chosen facet types tailored to your type of content and your users’ needs.
Another thing to consider is the choice of facet types. Most facet types are comparable in speed, but a few facet types will be faster than others to load. For example, an Autocomplete facet doesn’t need to calculate its choices on page load, so that’s fewer initial queries. The same is true for Date Range, Number Range, etc. Proximity facets used to be the slowest by far, but recent changes made it a lot faster.
As explained above, FacetWP’s filtering speed depends on how fast your uncached pages load. Important factors in this are the hardware and software your site is running on, your theme and plugins, and the efficiency of your template code. But the list of other things that you can do to increase performance is near endless. We wrote a separate tuturial on how to improve you page load speed to give an overview and get you started.
There are many tools and plugins you can use to debug and optimize your site’s code and analyze page loading times to determine the effectiveness of improvements you make. The recommended tool to do this is the free Query Monitor plugin.
Check out our tutorial about how you can use Query Monitor to optimize performance by optimizing the code and (number of) queries generated by your theme, listing template and loops, profiling your plugins, and optimizing your server setup.
One of the things that can help speed up your site enormously is to enable one or more caching solutions. But only some of the server-side caching solutions (like OPcache and object caching) will speed up FacetWP filtering.
If you have a high-traffic site, CDN caching can also help a lot in terms of caching all static assets (like images). With a CDN, images will load super fast around the world, and it will save a lot of bandwidth.
Check our tutorial about performance for an introduction to several types of server- and page caching and other things you can do to improve page load speed.
There are many WordPress caching/optimization plugins that each offer a range of different caching solutions, often combined with code optimization features like script minification, concatenation and deferring, image optimization, CDN image storage solutions, etc.
If you’re using a caching plugin with FacetWP, in general, make sure that HTML minification and script deferring is disabled. HTML minification is often problematic because – depending on the settings – it removes HTML comments, including the
<!--fwp-loop--> comments that FacetWP uses to automatically detect the query results. This often happens when users turn on Cloudflare’s Auto Minify feature. Sometimes you can exclude HTML comment from the minification process, which could prevent this (but test to make sure FacetWP is still working correctly). Script deferring is often problematic because of script timing issues.
If you are using the Pods plugin (which has built-in caching), experiment with the Pods Alternative Cache add-on plugin, especially if you are hosting your site on WP Engine.
For extra filtering speed you can enable FacetWP’s Caching add-on, which caches FacetWP’s own AJAX requests in the database. The Caching add-on can help speed up high-traffic pages by preventing FacetWP from having to calculate the choices for each facet on each page load.
Each unique facet filter combination that is used will be cached and retrieved from the cache the next time someone chooses that combination. If you have many users selecting a lot of different unique combinations (e.g. entering their own location or making random assortments of facet selections), then caching the AJAX requests isn’t going to help much because those combinations will not have been cached yet. So the Caching add-on will only be effective on frequently visited pages (like landing pages) with only a few facets and facet options/combinations that are used often.
The FacetWP Caching add-on doesn’t cache anything else than its own AJAX requests, so it will not negatively affect other caching systems you are using. It can be used side-by-side with other caching plugins, like WP Rocket, because most of them intentionally ignore AJAX requests.
Depending on how often your content changes, you may want to experiment with the cache expiration time. By default, the cache expires after 1 hour (3600 seconds). If your content only changes weekly or monthly, it would make sense to increase the cache lifetime as well. If your content rarely changes you could set the cache to a really long expiration time, then manually clear it when necessary. That’s actually what we do on facetwp.com because our demo content almost never changes.
FacetWP – on a WP search page and by extension in Search facets – uses WP Core search, which is extremely basic in functionality. It searches only titles and the content and excerpt fields for matches, and has no understanding of relevancy.
FacetWP’s main limitation in search speed is MySQL itself. Ultimately, MySQL is a general-purpose database and wasn’t built with the intention of being a scalable search engine.
FacetWP has built-in integration with SearchWP, which is much more flexible than WP Core search. It can search all your custom fields and has lots of features to fine-tune the relevancy of the returned results. It can even search pdfs and documents in your Media Libary.
For large sites, keep in mind that SearchWP has a much lower maximum post limit than FacetWP itself because all the advanced features and extra calculations SearchWP is doing behind the scenes require more server resources. SearchWP works best on a site with anywhere from a few posts to a few thousand. If your website has tens of thousands of posts or even hundreds of thousands, SearchWP does recommend not using it (see their FAQ).
Be aware that using Relevanssi may require large amounts (hundreds of MBs) of database space (for a reasonable estimate, multiply the size of your wp_posts database table by three). If your hosting setup has a limited amount of space for database tables, using Relevanssi may cause problems. The following information is from the Relevanssi site:
“The upper limit of how big a site Relevanssi can support depends on your hardware. On shared hosting accounts with limited resources, tens of thousands of posts can be too much. If your hardware is solid, especially your database, there’s probably no upper boundary. The biggest site we’ve heard run Relevanssi without problems had two million posts, using a dedicated database server with SSD drives.”
If you are expecting to have hundreds of thousands or even millions of results then you may want to look into Elasticsearch or Algolia, which FacetWP both doesn’t integrate with. These solutions offload search functionality to an external server that’s specialized in handling those searches, which will help speed up your site search.
Note that FacetWP does not fully integrate with ElasticPress. We have not tested ElasticPress with FacetWP ourselves, but some users have been able to get it working with Search facets specifically, for example with this script. But it does not work with other facet types which still require MySQL (the WordPress database) in order to function properly.
Also note that Elasticpress limits results to 10000 for performance reasons, so FacetWP will also not index or show more than 10000 results. See our Elasticpress page for a way to fix this, and tips on how to get Elasticpress working with FacetWP Search facets.
Algolia is a great service – we use it too on this site for the Help Center search. But there is no way to integrate Algolia with FacetWP and we have currently no plans to build this.
Algolia is very fast, mainly because all of its databases are in-memory. The drawback is that it’s expensive. Their pricing used to be more reasonable (and they even had their own in-house WordPress plugin), but years back they shifted focus towards enterprise clients.