All Products
Search
Document Center

:Configure an Apache caching policy

Last Updated:Sep 15, 2025

Configuring a web caching policy in Apache lets browsers and intermediate proxies, such as a Content Delivery Network (CDN), reuse downloaded resources, which reduces unnecessary network requests. This improves page load speed while decreasing server load and bandwidth consumption.

Note

Disclaimer: This topic may contain information about third-party products. Alibaba Cloud does not make any representations or warranties about the performance or reliability of third-party products. You are responsible for any potential impact from using these products.

Choose an Apache module

Apache module

Pros

Cons

Use cases

mod_expires

Simple syntax. Quickly sets expiration times for different file types.

Limited functionality. Cannot set Cache-Control directives like no-store or immutable.

Setting a simple cache duration (max-age) that tells browsers or CDN how long to reuse a file.

mod_headers

Provides full control over HTTP headers, supporting all Cache-Control directives, such as immutable.

Its syntax is more complex than mod_expires.

Production environments that require fine-grained and comprehensive caching strategies.

Procedure

Enable the modules

Before you configure a caching policy, ensure that the headers and expires modules are enabled in Apache.

  • To check if the modules are loaded, run the apachectl -M or httpd -M command. Verify that headers_module and expires_module are in the output list.

  • Enable the modules:

    • For Debian/Ubuntu:

      sudo a2enmod headers expires
      sudo systemctl restart apache2
    • For CentOS/RHEL/Alibaba Cloud Linux: These modules are typically compiled or loaded by default. If they are missing, check the configuration files in the /etc/httpd/conf.modules.d/ directory. Make sure the LoadModule lines are not commented out.

Choose a configuration file location

You can store cache configurations in a single file or in the VirtualHost block of your site.

  • Recommended: Create a new file, such as cache.conf, in the /etc/httpd/conf.d/ directory for CentOS/RHEL or the /etc/apache2/conf-available/ directory for Debian/Ubuntu.

  • Not recommended: Avoid making configurations in .htaccess files. Because Apache must read and parse .htaccess on every request, this causes unnecessary performance overhead.

Configuration examples

Set a global default cache expiration time

mod_expires

<IfModule mod_expires.c>
    # Enable the mod_expires feature
    ExpiresActive On
    # Set the default cache time for all resources to 1 day
    ExpiresDefault "access plus 1 day"
</IfModule>

mod_headers

<IfModule mod_headers.c>
    # Set the Cache-Control header. The cache time is 1 day
    Header set Cache-Control "max-age=86400, public"
</IfModule>

Set caching policies by file type

mod_expires

<IfModule mod_expires.c>
    # Enable the mod_expires feature
    ExpiresActive On

    # Set the default cache time to 1 day
    ExpiresDefault "access plus 1 day"

    # Cache image resources for 1 month
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/svg+xml "access plus 1 month"

    # Cache CSS and JS files for 1 week
    ExpiresByType text/css "access plus 1 week"
    ExpiresByType application/javascript "access plus 1 week"

    
</IfModule>

mod_headers

<IfModule mod_headers.c>
    # Cache image resources for 1 month
    <FilesMatch "\.(jpg|jpeg|png|gif|svg)$">
        Header set Cache-Control "max-age=2592000, public"
    </FilesMatch>

    # Cache CSS and JS files for 1 week
    <FilesMatch "\.(css|js)$">
        Header set Cache-Control "max-age=604800, public"
    </FilesMatch>
</IfModule>

Disable caching for specific resource types

mod_expires

<IfModule mod_expires.c>
    # Enable the mod_expires feature
    ExpiresActive On
    # Do not cache HTML files
    ExpiresByType text/html "access plus 0 seconds"
</IfModule>

mod_headers

<IfModule mod_headers.c>
    #  Disable caching for HTML files
    <FilesMatch "\.html$">
        Header set Cache-Control "no-store, no-cache, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires "0"
    </FilesMatch>
</IfModule>

Set a custom caching policy

Customize a policy using the following syntax rules of mod_expires and mod_headers:

mod_expires

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "base_time plus time_unit"
    ExpiresByType mime_type "base_time plus time_unit"
</IfModule>
  • ExpiresActive On: Enables the mod_expires module.

  • ExpiresDefault: Sets the default cache time for all resources that do not have a type defined.

  • ExpiresByType: Sets the cache time for a specific Multipurpose Internet Mail Extensions (MIME) type.

  • mime_type: Describes a file's format. It includes a main type and a subtype, separated by a slash, such as image/jpeg, or text/html.

  • base_time: The base time for caching. This is usually access (when the user accesses the file) or modification (when the file was last modified).

  • time_unit: The time unit, such as:

    • seconds

    • minutes

    • hours

    • days

    • weeks

    • months

    • years

mod_headers

<IfModule mod_headers.c>
    Header set|append|unset header_name "value"
</IfModule>
  • Header set: Sets the value of the specified HTTP header field.

  • Header append: Appends content to the existing value.

  • Header unset: Deletes the specified HTTP header field.

  • header_name: The name of the HTTP header field to operate on, such as Cache-Control or Expires.

  • value: The value to set.

Introduction to <FilesMatch>

The <FilesMatch> directive matches file names or paths using regular expressions. This lets you apply specific configuration rules to matching files. For example:

  • Set a long cache time for image files such as .jpg or .png.

  • Prevent access to sensitive files such as .htaccess or .log.

  • Add specific HTTP headers for static resources such as CSS and JS files.

Basic syntax of <FilesMatch> :

<FilesMatch "regular_expression"> </FilesMatch>
  • regular_expression: Used to match file names or paths. Common matching patterns:

    • \.(extension)$: Matches files with a specific extension. For example, \.(jpg|jpeg|png)$ matches all .jpg, .jpeg, and .png files.

    • ^/path/: Matches files within a specific path.

    • .*: Matches any file name.

Validate and apply the configuration

After you modify the configuration, check the syntax and then gracefully reload the service to avoid service interruptions.

  • Check the configuration syntax. Before you apply changes, run a syntax check command to ensure that there are no errors.

    • CentOS/RHEL/Alibaba Cloud Linux: sudo httpd -t

    • Debian/Ubuntu: sudo apache2ctl -t

    If the output is Syntax OK, you can proceed.

  • Apply the configuration (graceful reload recommended).

    Use the reload command to apply the new configuration without dropping existing connections.

    • CentOS/RHEL/Alibaba Cloud Linux: sudo systemctl reload httpd

    • Debian/Ubuntu: sudo systemctl reload apache2

Reference: How web caching works

Understanding web caching helps you correctly configuring Apache. Web caching is divided into two main types: strong caching and negotiated caching:

  • Strong caching: When a browser requests a resource, it first checks its local cache. If the cache is not expired (determined by the max-age directive in Cache-Control or the Expires header), the browser loads the resource from its local cache without contacting the server. The HTTP status code is typically 200 (from disk cache) or 200 (from memory cache). This is the most efficient caching method.

  • Negotiated caching: When a strong cache is invalid (expired) or not set, the browser sends a conditional request to the server to check if its cached version is still valid. This process involves these steps:

    1. The browser sends the request with cache identifiers in its headers, such as If-None-Match (with the ETag value from the previous response) or If-Modified-Since (with the Last-Modified date from the previous response).

    2. The server compares these identifiers with the current version of the resource.

    3. If the resource has not changed, the server returns a 304 Not Modified HTTP status code with an empty response body. The browser then continues to use its local, stale copy.

    4. If the resource has been updated, the server returns a 200 OK HTTP status code along with the new resource content.

By configuring Apache, you can control the following key HTTP response headers for your caching policy:

Cache-related HTTP response headers

Response header

Description

Common directives/values

Cache-Control

Introduced in HTTP/1.1 to provide fine-grained control over caching behavior. It takes precedence over Expires.

public: Can be stored by any cache (browser, CDN).

private: Can only be cached by the end user's browser.

no-cache: Forces negotiation caching. Must validate with the server every time.

no-store: Completely disables caching. Does not store any copies.

max-age=<seconds>: Sets the validity period for strong caching in seconds.

s-maxage=<seconds>: A max-age specifically for shared caches, such as a CDN.

must-revalidate: After the cache expires, it must be validated with the origin server. A stale copy cannot be used.

immutable: Indicates that the response body will not change while the cache is fresh. This lets the browser skip sending a conditional request.

Expires

An older HTTP/1.0 standard that provides an absolute expiration timestamp. This header is ignored if Cache-Control: max-age is present.

Expires: Wed, 21 Oct 2025 07:28:00 GMT

ETag

An entity tag (ETag) is a unique identifier generated by the server for a resource, such as a hash of the file's content. An ETag is more accurate than Last-Modified.

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Last-Modified

The time the resource was last modified on the server. It is less precise (second-level precision) and can be inaccurate in some scenarios, such as when file metadata changes but the content does not.

Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT