Title: Cache-control headers
Author: WordPress VIP Documentation
Published: August 3, 2023
Last modified: November 19, 2025

---

 1. [Caching](https://docs.wpvip.com/caching/)
 2. [Page cache](https://docs.wpvip.com/caching/page-cache/)
 3. [Customize page cache behavior](https://docs.wpvip.com/caching/page-cache/customize-behavior/)
 4. Cache-control headers

#  Cache-control headers

[The `cache-control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
specifies directives that control how browsers, CDNs, and proxies handle cached 
responses.

## Default values

Default `cache-control` response header values that are set by [VIP’s page cache](https://docs.wpvip.com/caching/page-cache/):

 * `cache-control: max-age=300, must-revalidate` (5 minutes) for most responses 
   with an HTTP Status Code of `200`.
 * `cache-control: max-age=31536000` (1 year) for [static asset files](https://docs.wpvip.com/caching/static-asset-caching/).
 *  `cache-control: private` for resources that are utilizing [VIP Cache personalization](https://docs.wpvip.com/caching/page-cache/the-vip-cache-personalization-api/).
 * `cache-control: no-cache, must-revalidate, max-age=0, no-store` when a request
   has bypassed the cache (`X-Cache: BYPASS`) and the response is from the origin.

On VIP, the `private`, `no-cache`, and `no-store` directives have identical behavior
and simply bypass the VIP edge cache.

## Modify a `cache-control` response header value

In most cases, the `cache-control` header value for WordPress and Node.js applications
can be set to custom [response directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives),
including:

 * `max-age`
 * `s-maxage`
 * `stale-while-revalidate`
 * `private` 
 * `no-cache`
 * `no-store`

## Limitations

The value of the `cache-control` response header for a resource **cannot** be set
to a custom value for:

 * Files that are stored in [the VIP File System](https://docs.wpvip.com/vip-file-system/).
 * Responses with status codes `301`, `302`, `307`, `404`, or `410`. 

## Modify the `s-maxage` value

The `s-maxage` response directive is honored by the page cache. If a `Cache-Control`
HTTP header contains an `s-maxage` response directive, the `s-maxage` value will
take precedence over `max-age`.

The values of the `max-age` or `s-maxage` response headers can be modified in order
to customize the duration of caching for static assets that are served by the origin
application web server.

**Caution**

Do not set `max-age` to less than 1 minute for heavily trafficked resource types.

 * Routes for site endpoints that rarely change should be set to a higher `max-age`
   value, which can improve the cache hit rate.
 * There is no upper limit to the value set for `max-age`, but increasing this value
   is only beneficial within a limited range. By default, cached page content is
   evicted from the cache according to the `max-age` TTL and [the `STALE` response](https://docs.wpvip.com/caching/page-cache/stale-responses/),
   which is set to 12 hours for content that is unable to be refreshed.
 * The page cache also relies on a Least Recently Used (LRU) strategy which will
   apply if the page cache is low in memory. As a result, setting `max-age` to a
   value beyond a certain range (e.g. > 24 hours) can result in content that is 
   requested less often to occupy valuable space in the page cache, which can lead
   to more frequent page cache evictions.

 * WordPress
 * Node.js

In this WordPress code example, `max-age` is set to a custom value for feeds. Note
that the example includes an `is_user_logged_in()` check. This ensures that the 
cache [Time To Live (TTL)](https://developer.mozilla.org/en-US/docs/Glossary/TTL)
headers are not set for logged-in users, as this would trigger browser caching for
them.

    ```lang-php
    add_action( 'wp', 'my_cache_maxage' );
    /**
     * Hooks the wp action to insert some cache control
     * max-age headers.
     *
     * @param Object wp The WP object, passed by reference
     * @return void
     */
    function my_cache_maxage( $wp ) {
        if ( is_feed() ) {
            // Set the max age for feeds to 10 minutes.
            if ( ! is_user_logged_in() ) {
                header( 'Cache-Control: max-age=' . ( 10 * MINUTE_IN_SECONDS ) );         
            }
        }
    }
    ```

In this Node.js code example, `max-age` is set to a custom value for an Express.
js route.

    ```lang-js
    const express = require( 'express' );

    const app = express();

    app.get( '/', function ( req, res ) {
      res
        .set( 'cache-control', 'max-age=3600' )
        .send( 'This response will be cached for 1 hour (3600 seconds)' );
    });
    ```

Last updated: November 19, 2025