Amazon S3 vs CloudFront: Why Delivering WordPress Media Directly From S3 is a Bad Idea

Amazon S3 is a sensible choice for storing your website’s assets in the cloud, but for delivery the benchmarks show that using a CDN is necessary to see any major performance gains.

I originally wrote this article back in 2016, and a whole lot has changed since then. WP Offload S3 is now WP Offload Media, we’ve reinvented the Assets Addon to the new Assets Pull addon, and we’ve learned a thing or two about deploying fast WordPress sites. So it seemed about time that I updated this article with all of that in mind.

If you’re reading this blog, you’re likely familiar with WP Offload Media, a plugin we offer that allows you to easily upload images and assets to Amazon S3. Storing these files on Amazon S3 is a great way to cut down on server space and keep your content in the cloud, but we highly advise against serving them directly from S3.

In this article, we’ll be benchmarking three common ways to serve assets from your website – directly from the server, directly from Amazon S3, and from a CDN, Amazon CloudFront.

About the Tests

Tests were run on website assets using ApacheBench, a command-line utility that lets you run hundreds or thousands of requests at a time to get a realistic picture of how your website is performing.

The website being tested was located on a DigitalOcean VPS in New York and had the default WordPress theme and no plugins other than WP Offload Media. Each benchmark sent 4 sets of 100 concurrent requests to an asset on the server itself, a nearby S3 server, and Amazon CloudFront.

I ran these tests from my local computer, located just outside of Philadelphia, and from a $5 DigitalOcean VPS located in Singapore to get a sense of how the tests would differ over large distances.

Delivering from the Web Server

Delivering from the same server your site is being served from is the most common method of serving assets and how WordPress does it out-of-the-box. The assets in these tests were loaded from a 2GB DigitalOcean VPS deployed in New York by SpinupWP, running NGINX over HTTP/2.

To get a baseline, I sent 400 requests for an image file delivered directly from the server.

Graph showing performance when loaded from the server (locally)

This resulted in an average load time of 140ms. Of course, this number will increase the further away the physical server is located since the assets are only being served from one location.

To illustrate that point, here’s the same test ran from a server located in Singapore:

Graph showing performance when loaded from the server (from Singapore)

This is a completely different story, with an average load time 1672ms, over a second. A website full of assets taking over a second to load borders on unusable, and I definitely wouldn’t stick around to wait it out.

Delivering from Amazon S3

This configuration is consistent with a basic configuration of the WP Offload Media plugin. The images and other media files are served directly from S3, while the CSS and JS files are still served from the server.

Running the same test on that image file loaded from S3 shows a slight increase in response time:

Graph showing performance when loaded from S3 (locally)

Yikes. Despite being served from Amazon’s high-availability servers, assets loaded from S3 took an average of 234ms, almost twice as long as the assets loaded directly from the server.

There could be several reasons for this. The VPS likely has an advantage in terms of sheer processing power, and the S3 bucket is mainly designed for storage with the expectation that Amazon CloudFront or another CDN be used for delivery.

The same test ran from our faraway server in Singapore did show a small improvement, with an average response time of 1482ms. Still, unacceptable performance:

Graph showing performance when loaded from S3 (from Singapore)

Delivering from Amazon CloudFront

Now let’s see if we can speed things up a bit. By creating an Amazon CloudFront distribution that pulls from the S3 bucket, we can tell WP Offload Media to deliver assets via Amazon CloudFront. This should result in more consistently fast loading times even in different locations due to the CDN edge servers that are close to the requesting user.

Graph showing performance when loaded from Cloudfront (locally)

Now we start seeing a small improvement. With an average response time of 137ms per request, it’s almost twice as fast as loading directly from S3, and slightly faster than loading directly from the server. However, that’s in an ideal situation, where the server is physically close to the person loading the asset.

When running the same test from Singapore, we can see that the improvement is much more pronounced:

Graph showing performance when loaded from Cloudfront (from Singapore)

There is one request that takes around 1,100ms, but that is likely due to the initial fetch of the image from the edge server. After that, with an average response time of 200ms per request, things are looking much better. An improvement like that can make the difference between a website being unusable and somewhat fast.

This goes to show that while offloading your images and assets to S3 can be a smart move to save space or backup your content, it shouldn’t be thought of as a massive performance boost. Depending on your location and proximity to the server, loading from S3 may actually hurt your performance more than help.

If you want your website to load quickly for a larger audience, a CDN is a no brainer, and will often be the fastest option. Have you run any of your own benchmarks or use a CDN to serve your assets? Let us know in the comments below.

About the Author

Matt Shaw Senior WordPress Developer

Matt is a WordPress plugin developer located near Philadelphia, PA. He loves to create awesome new tools with PHP, JavaScript, and whatever else he happens to get his hands on.