• Skip to main content
  • Skip to footer

TechGirlKB

Performance | Scalability | WordPress | Linux | Insights

  • Home
  • Speaking
  • Posts
    • Linux
    • Performance
    • Optimization
    • WordPress
    • Security
    • Scalability
  • About Janna Hilferty
  • Contact Me

Scalability

Understanding Cache-Control Headers

What is a header?

Whether you’re using a caching mechanism on your site’s server or not, Cache-Control headers are important to your site’s scalability and your end-user’s experience. Caching, or storing a copy of the completed request, can drastically help limit what requests your web server actually has to serve. But before we dive deeper into headers and cache, let’s first define: what are headers?

Headers are bits of contextual information your web browser can send and receive with requests for pages and files. Certain headers are sent with a request, while others are associated with the response you receive back. In this article we’ll be focusing on the “response headers” specifically. However, some of the directives we talk about are available for “request headers” as well.

With each request sent on the web, headers are returned. Here’s an example of the headers I get from my own domain:

The response headers tell me some information about my request.

HTTP/1.1 200 OK – This is the HTTP response code. It tells me whether my request was successful (200), redirected (301/302), received an error (500), or forbidden (403). There are tons of different status codes you might receive. Check out the full list for more information.

Server: Nginx – This section tells me the type of server that responded to my request. My site is hosted on a stack that uses Nginx as the web server software.

Date: Thu, 10 Aug 2017 17:00:29 – This is simply the date and time the response was served.

 

What are Cache-Control headers?

Sites may include many other kinds of headers, but I want to specifically call out two more:

Cache-Control: max-age=600, must-revalidate – This header defines how long my page should be cached for. The number is in seconds, so this example indicates a 10-minute cache time.

X-Cache: MISS – The X-Cache header indicates whether my request is served from cache on the server or not. MISS means my request is not already in cache. It passes to the web server to process, then stores a copy in cache on the way back. The next time I hit my site’s home page within the 10 minute cache window, it will serve it from cache.

 

What kind of cache are we controlling?

Cache-Control headers are responsible for controlling all caches, including (but not limited to): public, private, and server-level page caches. The Cache-Control header in my example above tells my web browser (Chrome in this case) how long to keep the response in its local browser cache.

Source: developers.google.com

It also tells the Varnish page cache on my server how long to cache the page.

Souce: book.varnish-software.com

The difference between the two is where the cache exists. In my Chrome browser, I’ve told Chrome to cache the page for 10 minutes with this response header. But what if I purge the cache in Chrome? Varnish page cache on my web server has still cached the response for 10 minutes. So I may still see the cached result from Varnish, unless I purge the page cache on the server too.

 

What kind of caching directives can I use?

There’s a long list of directives accepted for Cache-Control headers. Some are accepted only for Response headers, while others are also accepted on Request headers.

“public” or “private” directives are accepted only in Response headers. The “public” directive means the response can be cached by any service, regardless of whether you have HTTP Basic Authentication in use on the site or not. Meanwhile, “private” says to only cache in the browser and not in persistent caches, like my server’s Varnish page cache. It means the information on that page should only be cached for that user and not others.

“max-age” directives tell the caching mechanism how long to cache the response before it is considered “stale.” In my example the “max-age” is set to 600 seconds, or 10 minutes. The max-age directive can be used in Request and Response headers.

“must-revalidate” says that once the cached response is considered “stale” (after 10 minutes in my example), it has to be re-fetched/served as new. This directive is only accepted on Response headers.

“no-cache” and “no-store” relate to whether the cached response has to be re-validated by the server (check if the response is the same), and whether the response or content has to be re-downloaded. If “no-cache” is present, the cache mechanism cannot serve the cached response. Instead it must re-check if the response is the same. And if “no-store” is present, the cache mechanism cannot store the data/downloaded content and has to re-fetch the content again. These directives are accepted on both Request and Response headers.

Where do I set these headers?

There are several places you can define caching directives. If you’re one of many on the web using an Apache web server, you can set these directives in the .htaccess file. With an Nginx web server, you can set this in your Nginx configuration. If you use both, you’re probably using Nginx to handle all requests and pass certain ones to Apache. This means you should use the Nginx method of setting these headers.

If you don’t have access to the .htaccess file or Nginx configuration for your site, there are plugins out there which can configure this for you. W3 Total Cache or WP Super Cache both work great for this. If you’re using a host that offers server-level page cache like WP Engine, they take care of the configuration for you.

 

Apache or Nginx: The Web Server Showdown

Whether to use Apache or Nginx in your server stack is a decade-old question. While both web servers are versatile and open-source, both offer some pros and cons worth considering. Below I’ll break down some of the key differences between the two.


Architecture

One of the first aspects to consider is the way each web server handles requests. On Apache, there are several “multi-processing model” options to choose from. The most common is called “prefork” – in this model, there is a parent Apache process, with multiple “child” processes. With each new request that comes to the site, it opens a new “child” process. This allows your server to kill child processes in the form of individual requests, rather than having to kill the entire Apache service.

source: zope.org

With Nginx, the master process exists with any number of “worker” processes. However, the largest difference comes in that each “worker” can handle multiple (read: thousands) of page/resource requests at a time, without having to engage the other worker processes. This frees up the server resources that these worker processes would have used, to allow other services to use the Memory and CPU more dynamically. Nginx’s architecture allows the server to process high amounts of traffic while still leaving Memory unused, compared to Apache’s single-request-per-thread method.

Source: www.thegeekstuff.com

Compatibility

When Apache was built in 1995, it was an early success. Developers chose this web server model because of its flexibility and wide library of dynamically-loaded modules to extend its capabilities. By a year in, Apache dominated the web server markets by far. Because of its wide adoption rate, Apache documentation is vast. Many other software models integrate with and support Apache as a result.

Igor Sysoev originally developed Nginx in 2004 to be a web server to be used in combination with Apache. It was launched as a solution for sites which needed to serve thousands of simultaneous requests, which was a new horizon for the world wide web. As Apache’s adoption grew steadily, more modules extending its capabilities were released. When developers realized how lightweight the architecture ran on their hardware, it was an easy choice to begin using Nginx for static and dynamic requests.

As of today, Apache still holds about 50% market share of web servers, while Nginx holds about 35%.

Performance

When considering performance for Apache or Nginx, two main categories exist: static files, and dynamic content. Static files are files which don’t have to be regenerated when requested: images, css, fonts, and javascript. When your code constructs a page to be served, the content is dynamic. Other factors to consider here are: concurrent users, Memory used, transfer rate, and wait time.

In a base comparison of static files, Nginx is about twice as fast, and uses about 25% less memory:

Source: www.speedemy.com
Source: www.speedemy.com

And the same tester found that with dynamic requests, the web servers returned the responses in the exact same amount of time, when serving 16 concurrent requests:

Source: www.speedemy.com

However, remember the other aspects: what was the transfer rate? Do these results change with the number of concurrent users? Below is a comparison published by The Organic Agency:

Source: theorganicagency.com

You can see as the concurrent dynamic requests increase, so does the Apache response time. Nginx by contrast does show a load time increase as the concurrent users increase, but not nearly as much as Apache. Also consider the “failed requests” column which begins at about 25 concurrent users with Apache. Remember the architecture differences in how the servers handle multiple requests? This test is a clear indication of why Nginx is the model of choice for high-traffic environments.

Why not both?

Having trouble deciding whether you should use Apache or Nginx? Need versatility AND agility? No problem. There’s no reason you can’t use both web servers in your server stack. One common way to use both together is to use Nginx as a front-end server, and Apache as a back-end worker. This setup works because the performance disparity in the services is less noticeable for dynamic requests.

Using both servers allows Nginx to act as a “traffic director,” handling all requests initially. If the request is static, Nginx simply serves the file as-is. If the request is dynamic, Nginx uses a proxy_pass to send the request to the Apache web server. Apache processes the PHP and queries to generate the webpage, and sends it back up to Nginx to serve to your site’s visitor. If you’re looking to set this up on your own, check out Digital Ocean’s documentation on the subject.

 

 

Scaling a Forum Site

Help! My Site is Super Dynamic!

One of the most troublesome issues a developer or engineer can face is keeping your hosting cost low for a highly dynamic or inherently uncacheable site. How can a popular site that’s constantly updating scale well with spikes in traffic?

Many times the initial reaction will be: you simply can’t. Most systems that allow WordPress sites to scale well involve full-page caching, which simply isn’t an option for these types of sites. You need users to see the constant changes as they happen on the site, not minutes or hours later. These sites require a high level of dynamic content that is simply hard to accomplish.

Fragment Caching

If the budget simply won’t allow for more hardware, then it’s time to start thinking about what can and can’t be cached on the site. Is the header and footer going to always be the same no matter which user is on the site? Will the front page be the same? WordPress uses an Object Cache class which by default stores items wrapped in the wp_cache() function. By default the Object Cache is non-persistent, but you can couple it with Memcached to store the Object Cache items in Memory, to be served across all users.

By default WordPress will serve repeated query results from Object Cache. But really, anything you wrap in the wp_cache() function can be served from cache, including the HTML output from your header, footer, sidebar, and more. This is commonly known as “fragment caching.” WordPress provides some great examples of how to implement this on their Object Cache codex page.

Microcaching

On top of fragment caching, you may also consider using “Microcaching” at the Nginx level. This is a little-known process wherein Nginx caches your site’s static files like images, css, and javascript for long periods of time, while caching pages for a single second. This can vastly improve your site’s scalability if your site is constantly updating and changing. Check out the benchmarks in Microcaching WordPress in Nginx for a comprehensive example.

 

  • « Previous Page
  • Page 1
  • Page 2

Footer

Categories

  • Ansible
  • AWS
  • Git
  • Linux
  • Optimization
  • Performance
  • PHP
  • Scalability
  • Security
  • Uncategorized
  • WordPress

Copyright © 2025 · Atmosphere Pro on Genesis Framework · WordPress · Log in