1

I have a site with many custom queries. Some take many seconds to load a page. To solve that issue, I have been using a caching plugin. The issue is, my caching plugin does not cache a page until I click it once. I'd prefer to do this entire process without a plugin if possible. If the plugin route is the best way to go, I'd love to know that too.

I have an idea that this is how it SHOULD work, but I'd love to be corrected if this is impossible or not the best way...

When I upload a new post, I'd like the system to automatically cache all queries associated with the post, and save them to display to the user. If I add a new artist, I'd like their artist page to automatically be cached into the database. I'd prefer the user to never have to wait for a query, and instead to only see results of queries, printed.

The only 'live' part of the site needs to be the discussion forums and comment sections.

Is there a way to add to the code something like (on my side)"When i add a new post, check to see if any queries are affected by this change, if not, run a new query and store the results of this, if so, update the query to include this new information."

Then I want to display to the user only the result of the queries, filtered by the templates I have set up.

is there a way to persistently cache custom groups of posts together? Like could I run a query called $post_object_1_results ? then instead of the user running the query, I want the information to be pulled ffrom $post_object_1_results AFTER the query is run. Does a persistent version of wp_cache_set() and wp_cache_get(), exist?

Is a plugin the best way? Thank you

5
  • wp_cache_set an wp_cache_get don't perform page caching and only persist things for the duration of a request without a permanent object cache, which would require additional server software, they aren't the solution you were hoping for. Also checking on a new post if any queries are affected is not easy without running every single possible page to check. Keep in mind plugin recommendations are offtopic here, any answer you get would be code based and require some programming knowledge to implement as this is a developers stack
    – Tom J Nowell
    May 18, 2022 at 18:48
  • I am comfortable coding and programming if I can understand the logic. I would prefer a code - based answer, which is why I'm asking this question. I have an idea of more specifically how to address issues like that but hesitate to give specifics right now so people can answer my big question. For instance, when I add a new version, it's related to a release, which is related to an artist, so I would only need to update those pages. That is more specific than I want to get into yet. I'm looking for a broad approach and a start. Can anyone helP?
    – DJZEEGLER
    May 18, 2022 at 18:51
  • 2
    You need a specific question, I don't think mentioning hummingbird made the question offtopic as it was an example, but it was useful context. Don't approach this as a discussion topic, treat it as a specific question, remember you need to be able to mark an answer as correct, factually correct for all people with the same question, so avoid asking for opinions or ambiguities, and don't be broad it's literally one of the close reasons people can vote for. You can always ask multiple questions!
    – Tom J Nowell
    May 18, 2022 at 19:11
  • We use an nginx & php-fpm setup & there are some useful things you can do with static HTML caching there - setting headers with php to tell when to cache or not and under which keys. Cache served based on user role/cookies. This required a bit of work to set up - but allows us far greater flexibility and faster cache serve speed. There's quite a lot of blogs online about setting this up if you fancy some follow-up research. W/regards to pre-building cache - this is problematic - but a script that curls your main query-heavy pages would do the trick if you wanted to run something manually.
    – Bysander
    May 23, 2022 at 15:00
  • One of the most performant WP sites I've ever seen was using Cloudflare Workers to pre-render and deliver content to it's users. That has a lot of layers of course - because Cloudflare was not only rendering on-demand, but also distributing the rendered content across their CDN... It was a considerably static site, but definitely worth examination for other use-cases. It wasn't using the Cloudflare "APO" functionality - which in itself is probably worth inspection - but I think the CF offerings are still worth examination to other ends.
    – bosco
    Aug 8, 2022 at 23:53

2 Answers 2

3

No, there isn't. WordPress does not provide page caching mechanisms, and has no APIs for it. There is no generic way to say example.com/page is now stale and needs recreating. Nor is there any generic way to pre-generate every page short of visiting them all. Every plugin uses a different solution with different APIs and storage mechanisms.

As for knowing which parts of the site are stale and need recreating when a post is saved, unfortunately you've ran into a fundamental computer science problem, cache invalidation. When a post gets updated, there are only a handful of places you can know for certain that require cache invalidation/flushing/refreshing:

  • the posts main page
  • its RSS comment feed
  • its REST API response

Otherwise the only way to know where else might feature the post to flush it out is to visit the page and generate it. You can proactively try to invalidate its post parent, term archives for terms it features in, but this is a heuristic with no guarantees, and doesn't cover page templates, plugin generated interfaces, or other places such as the homepage. It also assumes your expensive queries completed and were able to generate a page that could be cached to begin with.

The only 'live' part of the site needs to be the discussion forums and comment sections.

If your posts change rarely you could empty the entire cache on update, it's expensive but effective. You'd need to research the specific caching solution you're using though. Otherwise bypassing page caching for those parts of the site is a plugin specific endeavour. The solution for say WP Supercache will be completely different to that for WP Rocket or another plugin.

what about wp_cache_set() and wp_cache_get(), is this the right kind of thinking?

This is the object cache, WordPress uses it to make sure it doesn't fetch the same post from the database twice. It's like cooking shows when they pull something from the under the counter and say "here's something I prepared earlier".

This won't fix your problem though, this cache is in memory only, so it's does not survive between page requests.

You can make it persist but it will require server software such as Redis/Memcached/Mongodb/etc and a suitable dropin PHP file to glue the two together. Most hosts do not provide this, and some managed/enterprise hosts provide it but do not give you the ability to configure it.

Even then, to use it you would need to build a page caching plugin from scratch, which leaves you back where you are at the moment with the Hummingbird plugin with the same questions. Plugins that use these two functions to store full pages already exist, and it's very likely you've already used them yourself without realising.

An Alternative

HTML is cheap and quick to render, it's the queries that are expensive, so why not cache those instead?

  • cache the queries, especially those using meta_query
  • fetching posts is cheap and fast, but figuring out which posts to fetch is expensive, so cache the post IDs, not the HTML
  • store the results either in transients, post meta, or if available, a persistent object cache

A Sidenote

Lots of people have these problems and find solutions who have never heard of WordPress, and people have struggled with caching for decades. There is no straightforward answer that can be recommended to you that you should install X, do Y, and Z will happen. Some solutions work very well, but won't work for you, and others will work but have caveats. Do you install something like varnish that sits infront of your server? Rely on a CDN like cloudflare? Do you cache for a very short time so the data is almost current, or permanently until told otherwise? etc etc. It's a game of tradeoffs, how current and recent do you want your data to be. Caching is no substitute for a fast page load, and ideally it's a way to scale your traffic, not the main thing making your pages load quickly/

16
  • Thank you for this awesome answer, this is exactly what I was looking for.
    – DJZEEGLER
    May 18, 2022 at 19:16
  • When you say cache the queries instead, what would that look like? That seems like a great idea to me. What is a persistent object cache? I think that's the kind of solution I'm looking for. You're right that the query is the slow part. I only need those bits to be 'glued'. What's the best way to do that?
    – DJZEEGLER
    May 18, 2022 at 19:18
  • Thank you for your patience, I'm unfamiliar with the language, and especially specific terms, so I'm sort of fishing for the right question to ask. Thank you
    – DJZEEGLER
    May 18, 2022 at 19:19
  • How would a transient look on the site? A transient converts a query to a static result for a limited amount of time?
    – DJZEEGLER
    May 18, 2022 at 19:20
  • And what is the kind of thing that makes pages load quickly? I'd love to remove all of the queries from my pages, then it's just html and printed results. Maybe what I'm fishing for is bigger than I realize. Each of my single pages has it's own custom query and loop on it. I only did that because I saw others do that, is there an alternative to that that would make the pages go faster? I understand the answer may be a big one, I just want to know how to start thinking about it correctly.
    – DJZEEGLER
    May 18, 2022 at 19:24
3

Ignoring some of the unique case details you provided, server-level page caching and object caching is nearly always the most efficient combination in terms of resource usage and scaling.

Specifically, LEMP stack is probably the most popular solution:

  • Nginx FastCGI cache for page caching (caches all of the HTML output by PHP-FPM)
  • Redis object cache (you'll need an object-cache.php for WordPress too)
  • PHP OPcache keeps getting better and more configurable also

Is there a way to add to the code something like (on my side)"When i add a new post, check to see if any queries are affected by this change, if not, run a new query and store the results of this, if so, update the query to include this new information."

This is pretty much how object caching works, and WordPress supports it quite well... if your server doesn't have object cache installed, WordPress "reverts" to using transients instead, which are like temporary files stored directly in the database... if object cache exists, it will store that data in e.g. Redis instead.

But like Tom mentioned, if you have tons of unique queries (or even if you don't) the final output is not going to be cached until those pages are actually visited... you can automate this, which is called warming the cache, but I don't recommend it for most situations because it uses a lot of server resources and might not even prioritize the pages/queries that are the most important per se. In other words, by the time you warm the cache or create a custom scripting solution to do it, and use a bunch of server resources too, was it worth it vs. just letting the first user visit that content and cache it for you instead? Not often...

If your website truly has a massive amount of custom queries that are rarely being called twice, getting on a cloud server with NVMe drives and CPU-optimized is going to help a lot, and is quite affordable... many of the major cloud providers offer these now.

Alternatively, if your site has lots of complex output, and many repeat hits, you could consider an output cache such Varnish which pretty much caches the hell out of the final code... but Varnish can be finicky and frustrating to optimize and manage, and I've seen it conflict with WordPress in some cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.