Blog

Servers & Hosting articles

Web Caching Explained: Browser, Server and CDN

Web caching explained layer by layer: browser cache, CDN, reverse proxy, page and object caching, Cache-Control headers and safe invalidation.

4 min read Servers & Hosting

The fastest request is the one your server never has to process. Web caching stores copies of content closer to the visitor, or in a ready-made form on the server, so pages load faster and servers handle more traffic with less hardware. Caching happens at several layers, each with its own rules and pitfalls. This article walks through them from the visitor's browser back to your database, and explains the HTTP headers that control them.

The layers of web caching

LayerWhere it livesWhat it storesControlled by
Browser cacheVisitor's deviceImages, CSS, JS, sometimes pagesHTTP response headers
CDN cacheEdge servers around the worldStatic files, optionally whole pagesHeaders plus CDN rules
Reverse proxy cacheIn front of your app (Nginx, Varnish)Generated HTML and API responsesProxy config and headers
Application page cacheInside the app or CMS pluginRendered pages or fragmentsApplication settings
Object cacheRedis or MemcachedQuery results, sessions, computed dataApplication code
Opcode cachePHP OPcacheCompiled PHP scriptsphp.ini

Browser caching

When a browser downloads a file, the response headers tell it whether and how long it may reuse that file. The main header is Cache-Control:

Cache-Control: public, max-age=31536000, immutable
  • max-age: seconds the response is considered fresh (31,536,000 is one year).
  • public: shared caches such as CDNs may store it. private restricts storage to the user's own browser, appropriate for personalised pages.
  • no-cache: may be stored, but must be revalidated with the server before each use. Despite the name, it does not mean "do not cache".
  • no-store: do not store at all; use for sensitive data such as account pages.
  • immutable: the file will never change at this URL, so the browser need not revalidate.

Revalidation uses ETag or Last-Modified headers. The browser asks "has this changed?" and, if not, the server replies 304 Not Modified with no body, saving bandwidth.

The safe pattern for static assets is versioned file names (app.4f2c1.js) with a one-year max-age, and short or revalidated caching for HTML. When you deploy, the HTML references new file names, so visitors pick up changes immediately.

In Nginx:

location ~* \.(?:css|js|woff2|png|jpg|webp|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Our HTTP header checker shows exactly which caching headers any URL returns.

CDN caching

A content delivery network (CDN) keeps copies of your content on servers in many locations. A visitor in Mumbai is served from a nearby edge rather than your origin server in Frankfurt, cutting latency, and your origin handles far fewer requests.

CDNs follow your Cache-Control headers by default, and many respect s-maxage, which applies only to shared caches. That lets you cache a page briefly at the CDN while browsers revalidate:

Cache-Control: public, max-age=0, s-maxage=300

Key CDN considerations:

  • Cache keys: which parts of the request (path, query string, cookies, headers) make a response unique. Too broad and the hit rate collapses; too narrow and users see each other's content.
  • Cookies: most CDNs bypass caching for responses that set cookies or requests carrying session cookies. Logged-in areas usually should not be edge-cached.
  • Purging: know how to clear specific URLs or tags after content changes.

Server-side caching

Reverse proxy and page caching

Generating a CMS page can involve dozens of database queries. A page cache stores the finished HTML and serves it directly to anonymous visitors. Options include Nginx FastCGI cache, Varnish, LiteSpeed Cache, or a CMS plugin. A minimal Nginx FastCGI cache:

# in the http block
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=PAGES:100m inactive=60m;

# in the http block: skip the cache for logged-in WordPress users
map $http_cookie $skip_cache {
    default 0;
    ~wordpress_logged_in 1;
}

# in the PHP location block
fastcgi_cache PAGES;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 10m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache-Status $upstream_cache_status;

The X-Cache-Status header (HIT, MISS, BYPASS) makes it easy to confirm the cache is working. Always bypass for logged-in users, carts, checkout and POST requests.

Object caching

Redis or Memcached keep frequently used data in memory: results of expensive queries, session data, configuration. WordPress, Magento, Laravel and most frameworks support them. Object caching helps even for logged-in users, where page caching is not possible. Keep Redis bound to localhost or a private network and protected with authentication.

Opcode caching

PHP's OPcache stores compiled scripts in memory so PHP does not re-read and parse source files on every request. It is bundled with PHP and should be enabled on every production server; check with php -i | grep opcache.enable.

Cache invalidation

The hard part of caching is making sure visitors do not see stale content. Practical strategies:

  • Versioned assets remove the problem for CSS, JS and images entirely.
  • Short TTLs for HTML (minutes) limit how stale a page can be.
  • Purge on publish: CMS plugins and CDN APIs can clear affected URLs when content changes.
  • Never cache personal data publicly. Mark account, cart and checkout pages private, no-store.

Common mistakes

  • Long cache times on unversioned files, so updates do not appear.
  • Caching pages that contain a logged-in user's name or cart at a shared layer.
  • Several caching plugins fighting each other in one CMS.
  • Forgetting that caching hides, rather than fixes, a very slow uncached page; cache misses still happen.

Designing a caching setup that is fast and safe is part of the tuning work in our server management service.

Key takeaways

  • Web caching operates at browser, CDN, reverse proxy, application, object and opcode layers.
  • Cache-Control headers drive browser and CDN behaviour; no-cache means revalidate, no-store means never store.
  • Use versioned static files with long lifetimes and short or revalidated caching for HTML.
  • Bypass shared caches for logged-in and personalised pages, and plan how to purge.

Need help with this?

Netifi helps businesses around the world with Servers & Hosting. Tell us what you are working on.