What is caching? Browser, page and object caches

Caching keeps a ready-made copy of something so it does not have to be built again. The layers that make websites fast, and when each one helps.

3–4 minutes
Cooling equipment on the roof of a data center

A cache is a stored copy of something that was expensive to produce, kept so the next request can be answered instantly. Websites use several layers of cache, each saving a different kind of work.

LayerStoresSaves
Browser cacheImages, styles and scripts on the visitor’s deviceDownloading files again
CDNCopies of files or pages near the visitorDistance and load on your server
Page cacheFinished HTML pages on your serverRunning PHP and database queries
Object cacheResults of database queries, in memoryRepeating the same query
Opcode cacheCompiled PHP codeRe-reading and compiling PHP files

Caching means keeping a ready-made copy of something so it does not have to be fetched or built again. On a website, caches exist at several layers, from the visitor’s browser to your server’s memory. A page cache alone often lets a small server handle many times more traffic.

Browser cache

Your server tells browsers how long to keep files with headers like Cache-Control: max-age=2592000 (30 days). Repeat visitors then load your images and styles from their own disk. Change a file’s name or add a version, such as style.css?ver=2, when you update it, so browsers fetch the new one.

Page cache

The biggest win for most sites. The first visitor to a page triggers the full work; the result is saved as a static file, and later visitors get that file. On WordPress this is done by a caching plugin or by the web server (for example Nginx’s FastCGI cache). See how much RAM a site needs for why this matters.

Page caching with Nginx

Without a plugin, Nginx can cache PHP pages itself. Define a cache in the http block:

fastcgi_cache_path /var/cache/nginx/site levels=1:2 keys_zone=SITE:32m max_size=512m inactive=24h;
fastcgi_cache_key "$scheme$host$request_method$request_uri";

Then, in the site, skip the cache for logged-in visitors and form posts, and use it for everyone else:

set $skip 0;
if ($request_method = POST) { set $skip 1; }
if ($http_cookie ~* "wordpress_logged_in|woocommerce_items_in_cart|comment_author") { set $skip 1; }
if ($request_uri ~* "^/(wp-admin|wp-login\.php|cart|checkout|my-account)") { set $skip 1; }

location ~ \.php$ {
    # ...the usual fastcgi lines
    fastcgi_cache SITE;
    fastcgi_cache_valid 200 301 1h;
    fastcgi_cache_bypass $skip;
    fastcgi_no_cache $skip;
    add_header X-Cache $upstream_cache_status;
}

The X-Cache header shows HIT, MISS or BYPASS, so you can check it is working with curl -sI https://example.com/ | grep -i x-cache. Clear the cache after publishing by deleting the cache folder’s contents, or set a short lifetime.

Object cache

A store in memory, such as Redis or Memcached, that keeps the results of database queries. It helps pages that cannot be fully cached, like shop carts and account pages.

To use Redis with WordPress, install the Redis server and the PHP extension, then a Redis object cache plugin:

sudo apt install redis-server php-redis
sudo systemctl restart php8.3-fpm

Object caching helps most on sites with many logged-in users, large shops and slow admin pages. On a small brochure site, a page cache does far more.

Opcode cache

PHP’s OPcache keeps compiled code in memory. It is built into PHP and should always be on.

Check it is on, and whether it has enough memory:

php -i | grep -E "opcache.enable |opcache.memory_consumption"

That shows the command-line PHP. The web version can differ; a phpinfo() page (removed straight afterwards) shows the PHP-FPM settings. On sites with many plugins, raising opcache.memory_consumption to 256 and opcache.max_accelerated_files to 20000 avoids recompiling.

When caching causes problems

  • You see an old version after an edit: clear the page cache or the CDN.
  • One visitor sees another’s data: a page meant for logged-in users was cached. Never page-cache carts, checkouts or account pages.
  • Changes do not show for everyone: different layers expire at different times. Clear from the top down: page cache, then CDN, then browser.

How to tell if caching is working

TestGood sign
Run curl -sI https://example.com/ twice and read the cache headerHIT from your page cache (x-cache) or CDN (cf-cache-status) on the second request
Time to first byte: curl -o /dev/null -s -w "%{time_starttransfer}\n" https://example.com/Under 0.2 seconds on the server’s own network for a cached page
Browser developer tools, Network tab, second visitStatic files show “(disk cache)” or “(memory cache)”

Something out of date? Software changes. If a step no longer works, tell us and we will check it and update the page.