Get your free SEO audit today Call 91 060 30 90
</>Technical Guide · 16 min read

HTTP caching and CDN: a technical performance guide

Every resource a server serves (HTML, CSS, JavaScript, images) can carry HTTP headers that tell the browser, and any intermediate cache between the server and the user, how long that resource can be reused without requesting it again. Getting these headers right is one of the performance optimizations with the best effort-to-result ratio: it doesn't require touching the page's code, only server configuration, and its effect on perceived speed for returning users is immediate.

Cache-Control: the header that replaced Expires

Cache-Control is the modern cache-control header, with several combinable directives. max-age specifies in seconds how long the resource can be considered "fresh" without checking again; public allows any intermediate cache (a CDN, a proxy) to store it, not just the user's own browser; private restricts storage to the user's browser, appropriate for personalized content; and immutable tells the browser that resource will never change content under that same URL, skipping even the check for whether it's still valid:

Header set Cache-Control "public, max-age=31536000, immutable"

The older Expires header served a similar purpose but with an absolute date instead of a relative duration, which made it more error-prone (a miscalculated date, an out-of-sync server clock); Cache-Control with max-age has replaced it in virtually every modern setup, though many servers still send both for compatibility.

ETag and Last-Modified: conditional validation

When the max-age period expires, the browser doesn't necessarily re-download the entire resource: it can make a conditional request asking "has this changed since last time?", using the ETag (a unique identifier that changes if the content changes) or the Last-Modified date. If the server confirms nothing changed, it responds with a 304 (Not Modified) status with no body, saving the full download; if it changed, it responds with the new resource and an updated ETag.

GET /style.css HTTP/1.1
If-None-Match: "a1b2c3d4"

HTTP/1.1 304 Not Modified
ETag: "a1b2c3d4"

The pattern that solves the tension between aggressive caching and fresh content

The risk of a very long cache (a year, as in the example above) is that, if that file's content changes (a CSS update, for example), users with the old version cached won't see the change until the full year expires. The standard solution, the one this very site already uses for its own CSS and JS files, is query-parameter versioning (style.css?v=139): every time the file's content changes, its URL changes too (as the version number changes), so the old cache is never reused for the new content, and it can be cached extremely aggressively (a year, immutable) with zero risk of serving outdated content.

What to cache aggressively and what to never cache

Static resources with a versioned name (CSS, JS, images with a hash or version parameter in the URL) are the ideal candidates for a year-long cache with immutable. Page HTML, on the other hand, usually shouldn't be cached aggressively (or should use no-cache, which always requires conditional validation before reusing the local copy) because its content changes more often and without an associated URL change; caching it as aggressively as versioned CSS would mean users see outdated content for days or weeks with no warning.

CDN: what it actually solves and why it reduces latency

A CDN (content delivery network) keeps copies of a site's static resources on geographically distributed servers, so a user in Australia doesn't have to wait for data to physically travel from an origin server in Europe, but instead receives it from the CDN node closest to their actual location. The effect is a direct reduction in network latency (the time it takes a data packet to go and come back), which is especially noticeable in Time to First Byte and, therefore, in the page's LCP, as explained in the Core Web Vitals guide.

Compression: Brotli versus gzip

Besides caching, compressing text (HTML, CSS, JavaScript, JSON) before sending it directly reduces the weight transferred without losing a single byte of information (it's lossless compression). gzip is the historical standard, universally supported; Brotli, developed by Google, compresses 15-25% better than gzip in most cases and today has practically universal support in modern browsers, making it the preferred option when the server supports it, with gzip as an automatic fallback for the rest.

The most common caching configuration mistakes in real audits

The most common is not caching at all static resources that never change content under their URL (a logo, a web font), missing out on a free optimization. The second is aggressively caching HTML of pages that change frequently, creating the outdated-content problem already described. The third, more subtle, is serving the same cache header through a CDN as through the origin server without accounting for the fact that many CDNs have their own additional caching layer (with its own, independently configurable lifetime), which can produce unexpected behavior if both layers aren't understood separately.

Frequently asked questions

Does browser caching directly affect SEO?

It isn't a ranking factor by itself, but it directly improves load speed for returning users, which does influence Core Web Vitals and the overall experience Google evaluates indirectly through those metrics.

Should I use a CDN even if my site only gets traffic from one country?

It still adds value even within a single country, because it distributes load and reduces latency at a regional level too, plus adds a layer of protection against unexpected traffic spikes that the origin server would otherwise have to absorb directly.

What happens if I cache a file aggressively and need to urgently fix a bug in it?

If the file uses query-parameter versioning, just upload the fix with a new version number: users will immediately download the fixed version because the URL has changed. Without versioning, you have to wait for the cache to expire or purge it manually on the CDN, if there is one.

Does Brotli completely replace gzip?

In practice they coexist: modern servers offer Brotli to browsers that support it and automatically fall back to gzip for the rest, via content negotiation based on the Accept-Encoding header each browser sends.

How long should I cache my pages' HTML?

For content that changes via the mini-CMS or similar, the usual approach is not caching it in the browser (no-cache) or using very short durations, letting a CDN cache or a server-side caching system (with the ability to purge immediately when a change is published) absorb most of the repeat traffic.

Want to talk about technical SEO for your site?

Tell us about your project and we'll tell you how we can help, no strings attached.

Call 91 060 30 90