I have been using Cloudflare and WordPress together for several years. It is a great choice as a free CDN, and it provides quality DNS and security features as well. As I have perused the blogosphere for methods to optimize a WordPress install and its underlying hosting stack, Cloudflare has come up frequently; but I had never discovered this “cache everything” tip before. This week, though, I found that I have been drastically under-using Cloudflare’s edge caching for the WordPress sites I host. I could turbocharge my sites by dynamically caching WordPress on Cloudflare.
Before I move on, I want to start by saying that this tactic is probably not beneficial on highly dynamic sites. If a site has posts going live all the time or maintains a high volume of comments, dynamically caching everything at the CDN level is probably not ideal. Every time a post or comment is updated, the edge cache has to be purged which requires a fair bit of overhead. However, for sites that do not change frequently, this tactic is working great.
Results
The default caching settings in Cloudflare only cache static portions of the site. These are things like images, CSS, etc. The HTML, though, is typically dynamically generated in a CMS like WordPress, so caching the HTML can prevent visitors from seeing recent updates. I have been serving everything including HTML from the CDN cache for a couple of days, though, and the numbers speak for themselves.
Fig. 1 shows the response times for my site from New Relic’s three U.S. nodes. It is very obvious where I flipped the switch to full page caching, reducing the response time at both of the West Coast nodes by about 70%.
Fig. 2 shows the average wait time drop across all New Relic Synthetics nodes. Again, the numbers do not lie; the wait time is cut globally by about 80%.
You can feel that speed by just clicking around my website. Lastly, if your site is insanely popular or if you hit it big on Product Hunt, Cloudflare will handle the massive influx of traffic with ease. Fig. 3 below shows 500 clients per second connecting to my homepage over 1 minute without any real problems. This is all served using only a $5 DigitalOcean Droplet.
Part 1. Cloudflare Page Rules
Implementing full page caching with WordPress requires two key components: Cloudflare Page Rules and the “Sunny” WordPress plugin to purge the CDN cache when the site is updated. Exactly 3 Page Rules are required to get this working properly, so as long as you do not need additional Page Rules, Cloudflare’s free plan works just fine. The page rules required are below; make sure to order them in the same way as they are listed.
The first rule ensures that Cloudflare does not cache dynamic content in the WordPress backend, which would, at best, prevent updates in the administrator panel from being visible; or, at worst, allow non-logged-in users to access your cached administrator dashboard.
mydomain.tld/wp-admin
- Custom caching: Default
- Browser cache expire TTL: 30 mins.
The second rule prevents page and post previews from being cached until the editor publishes them.
mydomain.tld/?p=
- Custom caching: Default
- Browser cache expire TTL: 30 mins.
The last rule is what then allows all other pages, posts, etc. to be served to visitors from Cloudflare’s CDN rather than from your origin server. I would recommend setting the browser cache (replacing {custom} in the third rule) for the public-facing pages to be about the max time between your site getting updated. So, for a blog with a new post daily and maybe a few comments daily, maybe 12 hours is good. If posts and comments are updated more frequently, drop that number down to as low as 30 mins. You want visitors to cache your content in their browsers as long as possible without having them miss new content.
mydomain.tld/
- Custom caching: Cache everything
- Edge cache expire TTL: Respect all existing headers
- Browser cache expire TTL: {custom} minutes
Part 2. Sunny by Typist Tech
At the time of this post, Sunny only has about 1,000 active installs, which is why I want to spread around this tip. This plugin is required if you do not want to log manually into Cloudflare and purge individual files every time you publish a new post. New posts, comments, etc. will not be visible to your visitors unless this plugin submits a cache purge API call to Cloudflare on your behalf. This request instructs Cloudflare to grab the latest of the related new files from your origin server. I have only been using the plugin for a couple of days, but it seems to work as expected. Thanks, Typist Tech, for the great little plugin. Follow their plugin installation instructions, and turbocharge your website by dynamically caching WordPress on Cloudflare!
Update 7.17.16: This site no longer uses this dynamic caching method. I have implemented NGINX micro caching in its stead. This change was primarily to take control of the site’s analytics; they are hosted locally with IP addresses hashed to protect the privacy of my visitors. Locally hosted analytics do not get updated when HTML is cached at the edge of the CDN.
Update 2.24.16: Sunny still does not purge RSS feeds. If this is necessary for your use case, here is a temporary workaround. Add the following code to your child theme’s functions.php, obviously modifying the URLs to match the feeds you would like to purge.
via GitHub
// purge RSS feed from Cloudflare via Sunny function purge_rss_cloudflare() { Sunny_Purger::purge_cloudflare_cache_by_url( 'https://example.com/feed/' ); Sunny_Purger::purge_cloudflare_cache_by_url( 'https://example.com/category1/feed/' ); Sunny_Purger::purge_cloudflare_cache_by_url( 'https://example.com/category2/feed/' ); Sunny_Purger::purge_cloudflare_cache_by_url( 'https://example.com/category3/feed/' ); } add_filter( 'publish_post', 'purge_rss_cloudflare' ); add_filter( 'private_to_published', 'purge_rss_cloudflare' ); add_filter( 'edit_post', 'purge_rss_cloudflare' ); add_filter( 'delete_post', 'purge_rss_cloudflare' );
Update 1.20.16: I have discovered that the current version of Sunny does not purge RSS feeds from Cloudflare. I hope to develop a pull request for this, but just be aware of your caching headers for RSS feeds if you try this method out.
via Typist Tech
Hi,
Congratulations for the detailed post!
Can you please explain what do you mean by:
“Respect all existing headers”
Best regards
Hi Agis,
“Respect all existing headers” is a setting for TTL that says that if a browser caching header is set by the server, respect that rather than overwriting it with the CloudFlare TTL. So, if you set CloudFlare TTL to 30 mins., but your webserver sets caching headers for a .jpg (for example) for 2 years, CloudFlare will not overwrite the 2 years header with the 30 mins. header. Does that make sense?
Never actually used sunny. Makes things a lot more convenient! Thansk for the share – I am now implementing it on a few sites to test!
I tried Sunny the other day before coming across this article. Sunny messed up my installation with the latest 4.6 install. I believe a conflict with WPSEO resulted in hundreds of near empty tables in my database because the two are constantly trying to run caches on each other. I’m not entirely certain but it’s worth taking a look if you have the two installed. When I went to uninstall Sunny, it also refused and I had to remove it manually via FTP and the tables with PHPMyAdmin.
Hmm, yeah, the Sunny developer seems to have gone dormant. His website domain has expired, and his Github account has been inactive for three months. It is quite possible there are plugin conflicts. Sorry for that inconvenience. I have experienced an uninstall bug and have opened an issue here, but I haven’t had a chance to look into a fix. That might have been the same issue you saw on your uninstall.
Hey @LunarStudio,
Did you find out what cause the conflict?
Hi,
I just released Sunny 2.
It purges RSS feed now.
Thanks for the post. I should have read this earlier.
Warning: Sunny 2 requires PHP 7.0 or later and WordPress 4.7 or later.
Great, thanks for that update! I don’t personally use Sunny anymore at the moment after getting Redis cache configured on my server, but I may go back to it at some point. It really is a neat little plugin.
Thanks for the great write up, that sunny plugin is a life saver.
Did the settings for Edge TTL change? I don’t see an option for it to “Respect all existing headers”
Hi Mike,
Glad to hear it helped! It does look like CloudFlare changed up the Page Rule caching settings a bit. See this article: https://support.cloudflare.com/hc/en-us/articles/200172266-What-do-the-custom-caching-options-mean-in-Page-Rules-
I think not specifying the Edge Cache TTL and setting the Cache Level to “Cache Everything” is the correct solution now.
Updating the article to reflect that.
Cache all HTML not safe for WooCommerce. Anyway you use Redis that is object cache not page cache (usually). Best page cache is FastCGI if you are gonna use Nginx.
I will choose light CloudFlare plugin: https://wordpress.org/plugins/cf-littlebizzy/
Because other is full of bugs. cheers
Hi Vlad,
See the first sentance of my second paragraph where I specify that this tactic is not recommended for highly dynamic sites (like WooCommerce).
The plugin you referenced, as far as I can tell, does not support auto-purge like Sunny. They serve different purposes.
Hi Nice Article
Can You explain NGINX micro caching
with this you meam fast cgi cache or anything else
as In comment you are saying that you dont use this Plugin any more so how do you make it work without any plugin
Please Share im Quite interested in it and want to use it
Hi Vibhi,
I use NGINX as my web server. It has the ability to cache HTML documents at its edge. This affords me the opportunity to have more immediate control over when cache gets invalidated than I can when all of my HTML is cached on Cloudflare.
But, the method described above still works well if for a fairly static site (HTML not changing frequently).
Hi Collin Thanks for replying.
I Know Nginx can Cache website which is way better than any WordPress plugin and Much faster
But What code You use or page rules
You use To cache your website in cloudflare
I Know One page rule is cache everything
but how do bypass cache in wp admin section
Hi Vibhi,
I use the rule described in this article for caching wp-admin. Look for the one with
mydomain.tld/wp-admin
.If you are asking how I configured NGINX to do the caching, that’s for another article, probable.
If I misunderstood your question, please let me know. Happy to help if I can.
@Collin M. Barrett
Well Can you tell me how did you clear the cache as you said in article that you stooped using sunny plugin
So I didn’t understand that how did you Handle that
If you are caching everything including the html document on CloudFlare, CloudFlare will still respect your cache headers. So, one way to handle this caching without the plugin is to specify a relatively short cache header. That’s actually what I have this blog configured to currently. For HTML documents, I have
cache-control:public, max-age=14400
header specified so CloudFlare will grab a fresh version every 4 hours.Not sure if that’s helpful…
Yeah Collin M. Barrett that’s exactly what i w anted to know lol Stupid me ??
Glad to hear it! It’s all good. I feel bad for taking a while to understand what you were asking. Glad to help.
Thank You very Much for helping me out
Can you write A Post about security header with apache and nginx
Well nginx is more important because I couldn’t find much info about it anywhere
Thanks for the suggestion. I have never really used Apache before, so probably can’t address it. I’ll consider it for NGINX.
Hi I used a different approach by adding a query for logged in user so it didn’t cache those pages but the main problem is Comment How do You tackle with this
When I comment it didn’t show the user Its comment what can i do?
Hi vibhi, yeah, comments are tricky. That’s why I made the notes that I did in the second paragraph. Sorry, I’m not using this solution any more personally, so you are kind of on your own. Good luck. Maybe contact the plugin developer to see what they would suggest.
I’ll start using a Plugin called supersonic it solve alot problem of simply like I can use cache everything in just three page but comments are problem i will replace it with thrid party comments
good post
Hii, Great Blog Post!
The Sunny Plugin is Great work on site server
Thanks for Share
Hii, Great Blog Post!
The Sunny Plugin is Great work on site
Thanks for Sharing
Nice Post share information about Dynamically Caching WordPress