Configuring Apache mod_expires for Effective HTTP Caching
Learn how to enable Apache's mod_expires, set expiration rules by MIME type, verify the headers, and avoid common pitfalls that lead to ineffective caching.
24 May 2026, 12:33 UTC

Useful answer
To add caching headers with Apache, enable the mod_expires module, turn it on for the desired scope, and set expiration rules by MIME type or as a fallback. This causes Apache to send Expires and Cache-Control headers that tell browsers how long they may reuse a resource.
How it works
The module calculates an expiration date in two ways:
access– the time of the client request plus the interval you specify.modification– the file’s last‑modified time plus the interval.
When ExpiresActive On is set, Apache evaluates ExpiresByType directives first; if none match, it falls back to ExpiresDefault. The resulting date is inserted into the response as an Expires header, and a matching Cache-Control: max-age=… header is added automatically.
Worked configuration example
Place the following in your virtual host file, .htaccess, or the main httpd.conf (requires reload or restart).
# Load the module if not already loaded (usually in httpd.conf) LoadModule expires_module modules/mod_expires.so ExpiresActive On # JPEG images cached for one month based on access time ExpiresByType image/jpeg "access plus 1 month" # PNG images cached for two weeks based on file modification time ExpiresByType image/png "modification plus 2 weeks" # Default fallback: one day for everything else ExpiresDefault "access plus 1 day"After editing, restart Apache:
sudo systemctl restart apache2 # Debian/Ubuntu # or sudo httpd -k restart # RHEL/CentOSVerification steps
- Request a JPEG file (replace
example.comand path with your own):curl -I http://example.com/images/photo.jpg- Look for headers similar to:
Expires: Thu, 14 Nov 2026 10:15:00 GMT Cache-Control: max-age=2592000The
Expiresdate should be roughly one month in the future from the request time, andmax-ageshould equal the number of seconds in that interval (2 592 000 for 30 days).- To confirm the fallback, request a file type without a specific rule (e.g., a CSS file) and verify that the
Expiresheader reflects theExpiresDefaultvalue (about one day ahead).Limits and common mistakes
- Module not loaded: If
LoadModule expires_moduleis missing orExpiresActive Off, no caching headers are added. Always checkapachectl -Mforexpires_module. - Over‑aggressive expiration: Setting very long intervals (e.g., "access plus 1 year") can serve stale content when the resource changes. Use versioned filenames or cache‑busting queries for assets that update frequently.
- Syntax errors: Misspelling
ExpiresByTypeor using an invalid interval (e.g., "access plus 1") causes Apache to ignore the directive; restart will fail with a syntax error. - Conflicting headers: If another module (like
mod_headers) manually setsExpiresorCache-Control, it may override or duplicate values. Test the final header set withcurl -I. - Missing reload: Editing the configuration without restarting or gracefully reloading leaves the old settings active. Use
sudo systemctl reload apache2orsudo httpd -k gracefulafter changes.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.