The Cache-Control: max-age=<seconds>, must-revalidate directive is used to specify the duration a resource should be cached while ensuring the client revalidates the resource with the server after the caching period expires. This provides a balance between performance and content freshness.

What Does It Do?

  • max-age=<seconds>: Defines how long (in seconds) a resource can be served from the cache without checking with the server.
  • must-revalidate: Ensures that after the max-age period expires, the client (browser or intermediary cache) must contact the server to verify if the resource is still valid.

Use Cases

  1. Time-Sensitive Content: Content that changes frequently but does not need to be revalidated for every request during its max-age period.
  2. Examples: News articles, API responses, event schedules.
  3. Reliable Freshness: Ensures users always get up-to-date content after the cache duration expires.
  4. Intermediate Cache Control: Prevents stale content from being served by intermediary caches (e.g., CDNs, proxies) without revalidation.

How It Works

  1. Within the Cache Period (max-age): The browser or cache serves the resource without contacting the server. Example: Cache-Control: max-age=600 (10 minutes).
  2. After max-age Expires: The client sends a conditional request (using If-Modified-Since or If-None-Match) to check if the resource has changed. If unchanged, the server responds with 304 Not Modified. If changed, the server sends the updated resource.

Configuration Examples

Apache

Add the following configuration to your .htaccess file or Apache configuration:

<IfModule mod_headers.c>
    <FilesMatch "\.(html|php)$">
        Header set Cache-Control "max-age=600, must-revalidate"
    </FilesMatch>
</IfModule>

This sets a 10-minute cache (max-age=600) for HTML and PHP files and requires revalidation after that.

Restart Apache to apply changes:

sudo systemctl restart apache2

Nginx

Edit your Nginx configuration file to include the Cache-Control header for specific file types:

location ~* \.(html|php)$ {
    add_header Cache-Control "max-age=600, must-revalidate";
}

Reload Nginx:

sudo systemctl reload nginx

PHP

Dynamically set caching headers for resources generated by PHP:

<?php
// Set a 10-minute cache duration with revalidation
header("Cache-Control: max-age=600, must-revalidate");

// Generate dynamic content
echo "This content is cached for 10 minutes but requires revalidation after that.";
?>

API Responses (Node.js Example)

Set Cache-Control headers for an API endpoint:

app.get('/api/data', (req, res) => {
    res.set('Cache-Control', 'max-age=300, must-revalidate');
    res.json({ message: 'This is temporary API data.' });
});

Example Scenarios

Scenario 1: News Page

  • Header: Cache-Control: max-age=300, must-revalidate
  • Behavior: Cached for 5 minutes. After 5 minutes, the browser checks with the server to ensure the news page is up to date.

Scenario 2: API Responses

  • Header: Cache-Control: max-age=120, must-revalidate
  • Behavior: API responses are cached for 2 minutes. After that, clients must revalidate to ensure they get the latest data.

Verifying Configuration

  1. Using cURL: Run the following command to inspect the headers:
  2. curl -I https://yourdomain.com/resource

    Expected Output:

    Cache-Control: max-age=600, must-revalidate
  3. Using Browser Developer Tools:
    • Open Developer Tools (F12).
    • Go to the Network tab.
    • Reload the page and inspect the headers of the requested resource.
  4. Using Online Tools: Use WebPageTest or GTmetrix to analyze caching headers.

Best Practices

  1. Set max-age Appropriately: Use a short duration for time-sensitive resources (e.g., 300 seconds for dynamic content).
  2. Combine with Validation Headers: Add ETag or Last-Modified headers for conditional requests.
  3. Avoid Overuse: Apply must-revalidate only when necessary to balance performance and freshness.
  4. Test Behavior: Verify that caches and clients handle revalidation correctly after the max-age period.

Example Response Headers

HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: max-age=300, must-revalidate
ETag: "12345"
Last-Modified: Tue, 19 Jan 2025 16:00:00 GMT

By using Cache-Control: max-age with must-revalidate, you can optimize caching for temporary or dynamic content while ensuring users receive up-to-date information after the caching period expires.