Apache response caching is useful when the same public asset or upstream response is requested repeatedly and the origin does not need to generate it every time. A working cache turns repeat requests into an X-Cache HIT from Apache instead of sending every request through the full content path again.
Apache HTTP caching uses mod_cache plus a storage backend. On Debian and Ubuntu, mod_cache_socache with the shmcb provider keeps small cache entries in shared memory, while larger responses usually belong in mod_cache_disk or an upstream cache layer.
The safe boundary is the URL pattern and the response's cache headers. Cache only public content, keep CacheQuickHandler off when authentication or authorization must still run, and attach the CACHE output filter in normal-handler mode so Apache stores the response after the normal request phases.
Related: How to enable or disable Apache modules
Related: How to test Apache configuration
Related: How to manage the Apache web server service
$ 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 Debian and Ubuntu.
$ sudo install -d -o www-data -g www-data -m 755 /var/cache/apache2/mod_cache_lock
On Debian and Ubuntu, the default Apache worker account is www-data. Use the account shown by sudo apache2ctl -t -D DUMP_RUN_CFG if your host uses a custom User or Group.
$ 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
CacheQuickHandler off CacheLock on CacheLockPath "/var/cache/apache2/mod_cache_lock" CacheLockMaxAge 5 CacheHeader on CacheDetailHeader on CacheSocache shmcb:/var/cache/apache2/mod_cache_socache(20971520) CacheSocacheMaxSize 512000 CacheSocacheMaxTime 86400 AddOutputFilterByType CACHE text/css text/javascript application/javascript image/png image/jpeg image/gif image/svg+xml image/webp image/x-icon font/woff font/woff2 <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 reused for the wrong client.
CacheHeader and CacheDetailHeader expose cache decisions during validation. Turn them off later if cache internals should not be visible to clients.
| Directive | Use |
|---|---|
| CacheQuickHandler off | 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 a cache entry is first created or refreshed. |
| CacheHeader | Adds X-Cache so cache hits and misses are visible during validation. |
| CacheDetailHeader | Adds the reason behind the cache decision while testing the rule. |
| CacheSocache | Selects the shared-object cache backend and its storage size. |
| CacheSocacheMaxSize | Sets the largest combined headers-and-body entry that socache will store. |
| AddOutputFilterByType CACHE | Places the CACHE filter in the normal-handler output chain for the listed MIME types. |
| CacheEnable | Tells Apache which URL patterns should be cached with the socache backend. |
$ sudo a2enconf cache-socache Enabling conf cache-socache. To activate the new configuration, you need to run: service apache2 reload
The command creates a symlink under /etc/apache2/conf-enabled/ so Apache loads the file on the next restart or reload.
$ 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
$ sudo systemctl restart apache2
Module changes require a restart. Later cache-rule-only changes can usually use sudo systemctl reload apache2 after a clean config test.
$ curl -sS -o /dev/null -D - http://www.example.net/assets/site.css HTTP/1.1 200 OK Date: Sat, 06 Jun 2026 03:38:38 GMT Server: Apache/2.4.66 (Ubuntu) Last-Modified: Sat, 06 Jun 2026 03:38:37 GMT ETag: "19-6538d833dbc4b" Accept-Ranges: bytes Content-Length: 25 Cache-Control: max-age=2592000 Expires: Mon, 06 Jul 2026 03:38:38 GMT X-Cache: MISS from host.example.net X-Cache-Detail: "cache miss: attempting entity save" from host.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.
$ curl -sS -o /dev/null -D - http://www.example.net/assets/site.css HTTP/1.1 200 OK Date: Sat, 06 Jun 2026 03:38:38 GMT Server: Apache/2.4.66 (Ubuntu) Last-Modified: Sat, 06 Jun 2026 03:38:37 GMT ETag: "19-6538d833dbc4b" Accept-Ranges: bytes Content-Length: 25 Cache-Control: max-age=2592000 Expires: Mon, 06 Jul 2026 03:38:38 GMT Age: 0 X-Cache: HIT from host.example.net X-Cache-Detail: "cache hit" from host.example.net Content-Type: text/css
If X-Cache stays at MISS, confirm that the response is not marked private or no-store, that the object fits within CacheSocacheMaxSize, and that the MIME type matches AddOutputFilterByType.
Tool: HTTP Header Checker