Response caching in Apache reduces repeated work for public assets and other reusable responses by serving them from a local cache instead of reading or generating them for every request. That lowers response time for clients and reduces avoidable load on the web server and the application behind it.
Apache HTTP caching is provided by mod_cache plus a storage backend such as mod_cache_socache or mod_cache_disk. The flow below uses mod_cache_socache on Ubuntu and Debian to cache small public files while freshness is still controlled by normal HTTP headers such as Cache-Control and Expires.
Cache scope is the real safety boundary. Keep personalized or authenticated URLs out of CacheEnable rules, and leave CacheQuickHandler off when cached content must still pass through the normal authorization flow. Shared-object caching also has entry size limits, so large files may need mod_cache_disk instead.
Related: How to enable or disable Apache modules
Related: How to test Apache configuration
Steps to enable response caching in Apache:
- Enable the Apache modules required for HTTP caching, shared-object storage, and freshness headers.
$ sudo a2enmod cache cache_socache socache_shmcb expires headers Enabling module cache. Considering dependency cache for cache_socache: Module cache already enabled Enabling module cache_socache. Enabling module socache_shmcb. Enabling module expires. Enabling module headers. To activate the new configuration, you need to run: service apache2 restart
These helper commands are part of the apache2 package layout on Ubuntu and Debian.
- Create a dedicated cache configuration file so the caching rules stay separate from the main server config.
$ sudo vi /etc/apache2/conf-available/cache-socache.conf
Use a virtual host file instead when only one site should be cached.
Related: Location for Apache configuration
- Add the caching directives for the public asset paths that should be reused.
CacheQuickHandler off CacheLock on CacheLockPath "/tmp/mod_cache-lock" CacheLockMaxAge 5 CacheHeader on CacheSocache shmcb:/var/cache/apache2/mod_cache_socache(20971520) CacheSocacheMaxSize 512000 CacheSocacheMaxTime 86400 <LocationMatch "\.(css|js|mjs|png|jpe?g|gif|svg|webp|ico|woff2?)$"> CacheEnable socache </LocationMatch> <IfModule mod_expires.c> <FilesMatch "\.(css|js|mjs|png|jpe?g|gif|svg|webp|ico|woff2?)$"> ExpiresActive On ExpiresDefault "access plus 1 month" </FilesMatch> </IfModule>
Keep CacheEnable rules limited to public content. Cached personalized pages, authenticated responses, or one-time downloads can be served to the wrong client or after the wrong login state.
The parent path for CacheLockPath must be writable by the Apache service account so lock files can be created during cache refresh.
Directive Use CacheQuickHandler Keeps Apache in the normal request path before serving cached content, which is safer when authorization rules still matter. CacheLock Reduces duplicate backend work while an entry is first created or refreshed. CacheHeader Adds X-Cache to the response so cache hits and misses are visible during validation. CacheSocache Selects the shared-object cache backend and its storage size. CacheSocacheMaxSize Sets the largest combined headers-and-body entry that socache will store. CacheEnable Tells Apache which URL patterns should be cached with the socache backend. - Enable the new configuration snippet.
$ sudo a2enconf cache-socache
The command creates a symlink under /etc/apache2/conf-enabled/ so Apache loads the file on the next restart.
- Test the configuration before restarting Apache.
$ sudo apache2ctl configtest Syntax OK
A warning about an unset global ServerName does not block the cache configuration from loading.
Related: How to test Apache configuration
- Restart Apache so the newly enabled modules and configuration take effect.
$ sudo systemctl restart apache2
In non-systemd environments such as some containers, use sudo apachectl -k restart instead.
- Request a cacheable asset once to populate the cache.
$ curl -sI http://127.0.0.1/assets/site.css HTTP/1.1 200 OK Date: Wed, 08 Apr 2026 04:07:26 GMT Server: Apache/2.4.58 (Ubuntu) Last-Modified: Wed, 08 Apr 2026 04:07:25 GMT ETag: "16-64eeb0999a26b" Accept-Ranges: bytes Content-Length: 22 Cache-Control: max-age=2592000 Expires: Fri, 08 May 2026 04:07:26 GMT X-Cache: MISS from web.example.net Content-Type: text/css
Use a public CSS, JavaScript, font, or image URL that matches the LocationMatch pattern. The first request is normally a MISS because the cache starts empty.
- Request the same asset again and confirm that Apache serves it from cache.
$ curl -sI http://127.0.0.1/assets/site.css HTTP/1.1 200 OK Date: Wed, 08 Apr 2026 04:07:26 GMT Server: Apache/2.4.58 (Ubuntu) Last-Modified: Wed, 08 Apr 2026 04:07:25 GMT ETag: "16-64eeb0999a26b" Accept-Ranges: bytes Content-Length: 22 Cache-Control: max-age=2592000 Expires: Fri, 08 May 2026 04:07:26 GMT Age: 0 X-Cache: HIT from web.example.net Content-Type: text/css
If X-Cache stays at MISS, confirm the response is not marked private or no-store and that the object fits within CacheSocacheMaxSize.
After validation, change CacheHeader to off if X-Cache should not be exposed in production responses.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
