Easy install Amazon CloudFront CDN with WordPress Plugin W3 Total Cache

Posted by Paul Braren on Jun 11 2014 in
  • Performance
  • WebDesign
  • Amazon-Web-Services-locations-map

    I've used AWS (Amazon Web Services) CloudFront off and on over the last few years, always on the hunt for the best CDN. What's a CDN? Content Delivery Networks can deliver your WordPress blog's rich media (images, video) to the far corners of the globe, taking a lot of the heavy work off of your web hosting provider, and offering better page load times to your visitors, across the globe.

    AWS S3 Bucket + AWS CloudFront + W3 Total Cache

    Amazon S3 Buckets as the "origin" for your CloudFront CDN is much more involved, such as these methods:
    Tutorial: Creating a CDN for WordPress with CloudFront and S3 July 19 2013, by victor
    How to Speed up WordPress with Amazon S3 & CloudFront as CDN September 26, 2013, by Jerry Wang

    These articles involve creation of a special AWS special user, then the hardening that user account with policies, and finally, special configuration of W3TC, which takes a bit of time, and is prone to errors. I believe I've found an easier way...

    AWS CloudFront + W3 Total Cache

    W3-Total-Cache-set-to-CDN-Type-Generic-Mirror

    The speed is excellent, much simpler to configure. My particular method in the videos (featured below) avoids nearly all of the complexity. From my before and after testing with TinkerTry.com, it sure appears to have results that are equally fast to my same tests that used S3.

    This article isn't about convincing you to go with one CDN versus another. Yeah, I've tried out MaxCDN as well, with very similar results most days, but some variability I couldn't seem to eliminate, and a slightly more difficult configuration. In the future, I may give Cloudflare another go as well, just to see how it compares, now that my web hosting provider Dediserve supports Cloudflare Railgun.

    AWS-CloudFront-testimonial-from-YouTube-viewer

    This article is for intermediate skill level site admins and content creators who want to find out exactly how to go about trying CloudFront CDN on your WordPress install, using some fairly straight forward variations of the CDN settings in super popular WordPress Plugin W3 Total Cache. There are no affiliate links in here, for AWS CloudFront, or for W3 Total Cache. Just info I gathered as I researched and prepared for these 2 videos I've created, seen below, where you'll get walked through, step by step, the actual process of setting this all up. Not a test or demo. Actually implemented, on this TinkerTry.com site.

    Step 1:

    Pingdom-Website-Speed-Test-for-TinkerTry.com-on-June-09-2014-with-W3TC-but-no-CDN

    Test the speed with various web page load speed tests available below, and be sure to test at least twice. Here's a quick and easy one to run:
    Pingdom Website Speed Test

    tools.pingdom.com/fpt

    Step 2:

    Follow the steps in this article:
    Amazon Cloudfront CDN with W3 Total Cache WordPress

    In the videos below, you'll notice that I included the optional step mentioned in the article, to visit your cPanel's Simple DNS Zone Editor to configure a CNAME, in my example (that's live now on this site), it's
    cdn.tinkertry.com

    Step 3:

    Follow the steps in this article:
    How to Setup WordPress Caching with W3 Total Cache (W3TC)

    In the videos, you'll note I skip the Database Cache and Object Cache options, not wishing to clutter my precious space on my Dediserve VPS hosting account (SSDs), with no speedup noticed even when I had turned those on for a previous test. Otherwise, I follow the instructions, exactly.

    Step 4:

    Make sure everything still works on my live site:

    What I didn't manage to capture on the video are two potential gotchas you might run into, due to the way all your media files will now be changed from something like

    https://tinkertry.com/image.png
    to
    http://cdn.tinkertry.com/image.png

    A) If you're using Amazon Publisher Studio script to load little 'Shop Now' buttons for images on your site, you'll need to add the following
    window.amznUseRelativeUrlsForImages=true;
    just before the Publisher Studio javascript on your website.

    B) If you are using a WordPress Plugin called nRelate Related Content, here's the steps to get it working again:
    nrelate.com/theblog/plugin-compatibility/w3-total-cache

    so now it's probably clearer why I'm considering this post an intermediate project, given there are numerous things that can go wrong with any caching. Export your config, and don't mess with it once you have it working.

    Step 5:

    Pingdom Website Speed Test
    tools.pingdom.com/fpt

    and make sure you've headed in the right direction, comparing your results with the previous test. Web page load times measured across the globe, over time, are superior to such moment in time tests, but I'll save that discussion for another day. I can say that there were 61 concurrent visitors to TinkerTry during the test seen below, recorded a couple of days after the videos below, with the same CloudFront and W3TC configuration.

    1.50-second-load-time-even-with-61-concurrent-visitors-on-June-12-2014-223pm-highlighted

    Feedback

    If there's demand screenshots and/or step-by-step written instructions, please drop me a comment below, no login required!

    The intended audience for the videos below are for intermediate web site admins, comfortable with making sure to do a full backup before getting started, perhaps with something like blogVault first. Things can go wrong, and you must have a plan for quick and easy, complete roll-back. Their support has been excellent:
    TinkerTry.com/blogvault

    Sites referenced in the videos

    Amazon CloudFront CDN Edge Locations:
    aws.amazon.com/about-aws/globalinfrastructure/regional-product-services

    Amazon CloudFront CDN with W3 Total Cache WordPress
    rtcamp.com/tutorials/cdn/amazon-cloudfront-wordpress-w3-total-cache

    Screenshot-of-CDN-article-alongside-AWS

    How to Setup WordPress Caching with W3 Total Cache (W3TC)
    wpexplorer.com/wordpress-w3-total-cache

    AWS CloudFront:
    console.aws.amazon.com/cloudfront/home
    aws.amazon.com/cloudfront/details
    aws.amazon.com/cloudfront

    W3 Total Cache Plugin:
    wordpress.org/plugins/w3-total-cache

    DNS-Propagation-Check-for-TinkerTry.com_

    Global DNS Propagation Checker:
    whatsmydns.net

    Pingdom Website Speed Test
    tools.pingdom.com/fpt

    Test a website's performance
    webpagetest.org

    GTmetrix Analyze Performance
    gtmetrix.com/dashboard.html

    Google Developers PageSpeed Insights
    developers.google.com/speed/pagespeed/insights

    What this site uses
    TinkerTry.com/what-this-site-uses

    Uptime, Response Time, and Status
    TinkerTry.com/uptime-response-time-and-status

    Step by Step Walk Through Videos

    Easy install and test Amazon CloudFront CDN with W3 Total Cache for WordPress:

    Easy install and test Amazon CloudFront CDN with W3 Total Cache for WordPress,
    with informal page load speed testing before, during, and after:


    Aug 01 2014 Update

    I have found AWS Support (Developer level) ($49/month, can cancel at any time) to be very knowledgeable. I had some detailed questions that closely relate to the article above. I'm glad to share some very detailed answers I received.

    I reversed the order of the service ticket timeline, to make this an easier read, oldest to newest. I also removed extraneous footer stuff like " We value your feedback. Please rate my response using the link below."

    Other than those 2 alterations, I left the content as-is. Here's a highlight (part of the reason I avoided using S3 in the first place):

    This is what we call "Invalidations":
    http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
    We charge for invalidation objects, so I would not recommend that you rely on invalidating objects very often.

    Here's the entire case/transcript:

    Paul Braren
    Jul 03, 2014
    12:45 PM PDT
    Was hoping for a forum response to my query from Jun 9 2014 here:
    https://forums.aws.amazon.com/click.jspa?searchID=5810373&messageID=549038

    Would you be able to provide any guidance on this question?

    Distribution IDs or URLs: d3ri3zyd4v0fag.cloudfront.net

    |

    Paul Braren
    Jul 03, 2014
    12:47 PM PDT
    So far, after a month on AWS CloudFront, things going well, but want to be sure I'm not misleading folks in my article:
    https://tinkertry.com/easy-install-amazon-cloudfront-cdn-with-wordpress-plugin-w3-total-cache/
    just in case there's some disadvantage to not using S3 that I'm not aware of.
    Thanks!

    |

    Amazon Web Services
    Jul 04, 2014
    12:03 PM PDT
    Hi,

    I apologize for the delay in getting back to you. One of the main benefits of S3 over a custom origin for serving static content would be the redundancy of storage and the lack of a single point of failure. Running off of a single instance, server, or VPS as a custom origin would keep CloudFront from accessing content on your origin in the event of a power or disk event. This is not true of S3 as your objects are stored across multiple availability zones.

    The speed of fetching items from the origin will differ in both custom and S3 origins based on latency from the particular CloudFront edge location and the origin. Please let me know if you have questions. Thanks!

    Best regards,

    Scott W.
    Amazon Web Services
    We value your feedback. Please rate my response using the link below.

    |

    Paul Braren
    Jul 04, 2014
    01:59 PM PDT
    Hey Scott W., thank you for the response, no hurry on any of this, and I realize it's now a holiday in the US.

    So, given I’m running a WordPress site www.tinkertry.com, I fully expect it to go down if my hosting provider Dediserve goes down (new New York City). So it seems the disadvantages (of not using S3) are minimal for my situation.

    In other words, if my origin www.tinkertry.com web hosting or apache server goes down for any reason, I don't expect Amazon CDN to keep any of my content going.

    Let me see if I have this right, as far as the way CloudFront is currently working for me (without S3).

    Any overseas visitor who is the first in world to visit a particular article of mine (of 450 articles) probably gets a slower experience than they would have had, had I used S3 storage. The logic is that the time to pull from that origin (NYC) is slower than it would have been from S3 (spread all over the globe). The URL that their browser is requesting data from is still be cdn.tinkertry.com for those resources (typically PNGs), but CloudFront doesn't have those PNGs in its cache yet, so it has to pull from www.tinkertry.com behind the scenes, to get that content displayed for the first time visitor.

    For all viewers of that same article after that, they get the media from cdn.tinkertry.com as well, but this time, it's much closer/faster for them (using one of the many CloudFront locations across the globe):
    http://aws.amazon.com/cloudfront/details/

    Does this sound about right? I have no control or visibility of how CloudFront is storing my files, I do wonder if those really are spread around the globe automatically somehow, this same article:
    http://aws.amazon.com/cloudfront/details/
    really doesn't say.

    Purging is another issue, also not well documented or understood. For example, this article:
    https://rtcamp.com/tutorials/cdn/amazon-cloudfront-wordpress-w3-total-cache/
    which states:

    "Many users asked why we are using Generic Mirror when Amazon CloudFront option is already in dropdown menu.

    On many occasions, Amazon CloudFront option did not work for us. Though, it that option works for you. Please use it. Most likely, using Amazon CloudFront way will purge your CDN cache automatically from WordPress dashboard. BUT, Amazon CloudFront charges for cache-purge also. So accidental and unnecessary purges will increase you bill."

    Is this true?

    Do you have a wiki, FAQ, or kb article for me, to get up to speed on this?

    I appreciate your patience with me, as I don't claim to be a web developer, instead, a content producer using WordPress, and looking for affordable ways to use CDN to speed up my site, having been burned heavily by the complexity of troubleshooting CloudFlare, I'm always looking to keep things simple, which so far seems to be outperforming MaxCDN and CloudFlare, for my site.

    |

    Amazon Web Services
    Jul 06, 2014
    03:31 AM PDT
    Hello,

    Thank you for your reply.

    I would like to provide you clarification in relation to some points.

    You quoted:
    ""Any overseas visitor who is the first in world to visit a particular article of mine (of 450 articles) probably gets a slower experience than they would have had, had I used S3 storage. The logic is that the time to pull from that origin (NYC) is slower than it would have been from S3 (spread all over the globe).""

    S3 servers are not spread all over the globe. When you create a S3 bucket to store your content you select a region. The S3 content is distributed in different servers in that region in order to provide redundancy and durability.

    As S3 cannot be used to store dynamic content i.e.: php files, you use S3 to store static content i.e. PNG images as you mentioned earlier. Placing the static content in S3 instead of your server can have some advantages such as:

    • Your web server will require less compute capacity and bandwidth since part of the content is distributed from S3.
      For example instead of processing and delivering a php file and 5 images, the web server would work only on processing and delivering the PHP while the images would be served from S3.
    • S3 content is designed to provide data durability and availability 99,9%. (Please note that backups of the actual content should be always taken).

    In relation to CloudFront, you are right. CouldFront will not proactively pre-cache the content. The first request will be a "Miss from CloudFront" and successive request will be a "Hit from CloudFront". This always be the default behavior regardless the origin that you are using to serve the content (your web server or S3).

    I would like to address your question:
    ""
    I have no control or visibility of how CloudFront is storing my files, I do wonder if those really are spread around the globe automatically somehow, this same article:
    http://aws.amazon.com/cloudfront/details/
    really doesn't say.
    ""

    We currently do not have a tool such as a control panel or API call that you can use to query Amazon which objects are currently stored in CloudFront servers and in which locations. However, you can know when a request was served from CloudFront or not.

    For example In Chrome or Firefox, right click on the browser (in the area where the web pages are displayed) and in the contextual menu select "Inspect Element". Then go to your website https://tinkertry.com.
    Click on the "Network tab". Click on one of the GET files served by cdn.tinkertry.com
    On the right side, you will see response headers. Look for the header X-Cache. When X-Cache is Miss from CloudFront it means that CloudFront had to request the object to the origin. When you get a "Hit from CloudFront" it means that the object was served from a CloudFront edge location.

    About purging the cache:
    This is what we call "Invalidations":
    http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
    We charge for invalidation objects, so I would not recommend that you rely on invalidating objects very often.

    You should focus your effort on determining how long time you want to keep the content in cache. You can configure CloudFront to cache the content for a short or a long time. Depending on what you choose, there are advantages or disadvantages.

    Configuring CloudFront to cache content for longer periods of time can improve the performance.
    For example:
    Caching an image mylogo.png for 24h, will make all the successive requests going to the same edge location within the next 24h to be served by CloudFront.
    The downside of this, it is that if you want to update mylogo.png with a new version, it can take 24h for the clients to be able to display the new mylogo.png.

    If you choose a low caching time i.e. 60 seconds, the newlogo.png will be visible for all the clients very quickly, however the performance can decrease as you would be serving content from CloudFront to successive request only for 60 seconds, after that time we ask the origin if it has new versions of the object.

    Does it make sense? How long time the content should be in cache, it is a decision that is up to you.

    ** As conclusion **

    • Your web server can serve the dynamic content .php files.
    • S3 or your web server can server the images (see above the advantages of S3).
    • CloudFront would be place in front of your web server or S3 and would cache the content upon request.

    * Example loading www.tinkertry.com**
    1) You resolve the www.tinkertry.com. The computer resolves the name and goes to the IP of your server i.e.: 50.0.0.1 (this is not a real IP)
    2) The client request i.e. index.php, this goes directly to the web server. The PHP server genreates the HTML content for the browser.
    3) Once I get index.php, I have to load an image from src=cdn.tinkertry.com/image.png
    4) The client resolves cdn.tinkertry.com and gets an IP that points to the CloudFront edge location with best latency measures for tha client.
    5) CloudFront gets the request, but the first time it does not have the image.png in cache "Miss from CloudFront". It request the image to the origin (www.tinkertry.com or S3 - as you prefer).
    6) CloudFront gets the origin serves it and stores it for successive requests. How long time the image will be stored in the edge location will depend on your cache settings.

    Please let me know if that gives you a better understanding.

    I will be happy to assist you.

    Best regards,

    Alejandro M.
    Amazon Web Services
    We value your feedback. Please rate my response using the link below.

    |

    Amazon Web Services
    Jul 10, 2014
    03:41 AM PDT
    Hello,

    We haven't heard back from you regarding case 217868781 for a while. For continued support regarding the same issue, you can contact us any time using the following URL:
    https://aws.amazon.com/support/case?language=en&caseId=217868781

    Please note that no action is required on your part if you wish this case to be resolved. However, if you want to close this case yourself, you could do so via the Support Center. If we haven't heard back from you within the next 48 hours we will mark the case as Resolved, although you can re-open the case any time using the link above.

    Best Regards,

    Amazon Web Services

    |

    Paul Braren
    Jul 10, 2014
    06:42 AM PDT
    Your reply was astoundingly details, and greatly appreciated.

    One point of clarification would be about this section:
    You should focus your effort on determining how long time you want to keep the content in cache. You can configure CloudFront to cache the content for a short or a long time."

    Are you talking about .htaccess tweaks that W3TC makes, adjusting expiration for resources like PNG files?

    I ask because back when I was trying the CDN that my hosting provider Dediserve offers, they asked me what value I wanted to them to set for their CDN resource, which I found strange (it seemed to ignore my .htaccess settings).

    |

    Amazon Web Services
    Jul 10, 2014
    07:46 AM PDT
    Hi,

    Thank you for getting back to us.

    To add on to my colleague's response, you can adjust TTL on certain paths (in your particular case *.PNG). For example, if you update your images quite often (ie every 24 hours), you can set your TTL for objects that have a file extension of PNG to 86400 (24 hours). This will tell CloudFront that your object is stale after that time. Once an object is marked as stale, CloudFront will check with the origin to see if the object has been updated. If the object has been updated, it will fetch the latest object.

    Additionally, if you're looking to specify expiration settings on specific objects or paths, you can configure a behavior path. Configuring a behavior path will allow you to specify certain object expiration depending on their path, or their file type. For example if you want all objects in the directory called Example (/example/) to expire after 3 hours, you can set it to do so by setting your TTL to 10800. Similarly, if you wanted objects that were of file type PNG to expire after 3 hours (.PNG) you can set the TTL to 10800.

    Now to answer your question directly (Are you talking about .htaccess tweaks that W3TC makes, adjusting expiration for resources like PNG files?) - Editing the cache control headers on a server level allow you more flexibility. There are various headers with regard to Cache-Control that you can set (some of which we respect and some of which we override). With that being said, different CDNs may respect or ignore certain headers depending on the CDN.

    Our documentation contains a chart that may be useful to you (included below). Additionally, I will include other links that you may find useful when configuring your expiration settings.

    How CloudFront will cache objects depending on your headers - http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html#ExpirationDownloadDist

    Cache Behaviors - http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesCacheBehavior

    Cache-Control Directive Options (these should be double-checked with the first link to understand how CF may treat these) - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9

    I hope this clarifies your concerns. If you have any questions, please don't hesitate to reach out to us.

    Best regards,

    Moustafa G.
    Amazon Web Services

    |

    Amazon Web Services
    Jul 14, 2014
    01:13 PM PDT
    Hello,

    We haven't heard back from you regarding case 217868781 for a while. For continued support regarding the same issue, you can contact us any time using the following URL:
    https://aws.amazon.com/support/case?language=en&caseId=217868781

    Please note that no action is required on your part if you wish this case to be resolved. However, if you want to close this case yourself, you could do so via the Support Center. If we haven't heard back from you within the next 48 hours we will mark the case as Resolved, although you can re-open the case any time using the link above.

    Best Regards,

    Amazon Web Services

    |

    Amazon Web Services
    Jul 16, 2014
    02:14 PM PDT
    Hello,

    We haven't heard back from you regarding this case. At this time, we're marking this case as Resolved. However, if you're still experiencing issues, we want to hear from you! Please re-open this case for continued support:

    https://aws.amazon.com/support/case?language=en&caseId=217868781

    Best regards,

    Amazon Web Services

    |

    Paul Braren

    Jul 21, 2014
    06:28 AM PDT
    I'm all set with this case, your information is excellent.
    Any objection to me publishing some or all of your excellent info? I can remove the firstnames/last initials, if you prefer.
    Thanks again!

    |

    Amazon Web Services
    Jul 22, 2014
    06:42 AM PDT
    Hi,

    I'm glad we were able to get everything working for you!

    Feel free to re-purpose our suggestions and clarifications as needed.

    As always, we're here to help, so if you have any other questions or concerns, please don't hesitate to reach out to us at any time. Have a great day!

    Best regards,

    Moustafa G.
    Amazon Web Services
    We value your feedback. Please rate my response using the link below.