max-age

Caching

Specifies the maximum time in seconds that a response is considered fresh. Applies to all caches (browser, CDN, proxies). After this time expires, the cache must revalidate or fetch a new copy.

Updated Apr 3, 2026

Full Explanation

max-age is the workhorse of Cache-Control. It tells every cache in the chain (browser, CDN, reverse proxy) how many seconds a response stays fresh. Set Cache-Control: public, max-age=3600 and that response is good for one hour. No conditional requests, no round trips to origin. The cache just serves it.

Once that timer runs out, the cached copy is considered stale. The cache then has to revalidate with the origin (usually via If-None-Match or If-Modified-Since) or fetch a completely new copy. If you want shared caches like CDNs to use a different TTL than browsers, use s-maxage to override max-age for those shared caches only.

Here is how you would set it in nginx for different content types:

# Static assets: cache for 1 year
location ~* \.(css|js|png|jpg|webp|avif|woff2)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# HTML pages: cache for 10 minutes
location / {
    add_header Cache-Control "public, max-age=600";
}

# API responses: cache for 30 seconds
location /api/ {
    add_header Cache-Control "public, max-age=30";
}

The key thing to remember: max-age starts counting from when the response was generated, not from when the cache stored it. If a response travels through multiple hops, each cache uses the Age header to figure out how much freshness lifetime is left.

Examples

Static assets with content hashes in their filenames can be cached aggressively because the URL changes when the file changes:

Cache-Control: public, max-age=31536000, immutable

API responses that change frequently need a short max-age:

Cache-Control: public, max-age=30

For a typical website homepage, something in between works well. Cache for 10 minutes in the browser but let the CDN hold it for an hour:

Cache-Control: public, max-age=600, s-maxage=3600

Frequently Asked Questions

Specifies the maximum time in seconds that a response is considered fresh. Applies to all caches (browser, CDN, proxies). After this time expires, the cache must revalidate or fetch a new copy.

Static assets with content hashes in their filenames can be cached aggressively because the URL changes when the file changes:

Cache-Control: public, max-age=31536000, immutable

API responses that change frequently need a short max-age:

Cache-Control: public, max-age=30

For a typical website homepage, something in between works well. Cache for 10 minutes in the browser but let the CDN hold it for an hour:

Cache-Control: public, max-age=600, s-maxage=3600

Related CDN concepts include:

  • s-maxage — Stands for "shared max-age". Overrides max-age specifically for shared caches (CDNs, reverse proxies). Browser caches …