Tuning the Apache access log removes a surprisingly common bottleneck on busy sites: per-request log formatting and frequent small writes to disk. Reducing that overhead improves tail latency during traffic spikes, keeps CPU cycles available for actual request handling, and slows the growth of log volume on storage.

Access logging is handled by mod_log_config, primarily through LogFormat (what gets written) and CustomLog (where it goes). Every additional field in the format string can add work, especially when headers are referenced, and every logged request adds I/O. Conditional logging (via env=…) can skip low-value requests entirely, which often yields the largest real-world improvement.

Logging changes trade detail for speed. Removing fields or skipping endpoints can reduce forensic and audit value, and buffering can lose the last few entries during a crash. Examples below assume a Debian or Ubuntu layout (/etc/apache2, /var/log/apache2, service apache2); RHEL-family systems typically use /etc/httpd, /var/log/httpd, service httpd.

Steps to optimize Apache access log performance:

  1. Locate the active CustomLog directive that writes the access log.
    $ sudo grep -R --line-number --extended-regexp '^[[:space:]]*(CustomLog|LogFormat|HostnameLookups|BufferedLogs)' /etc/apache2
    /etc/apache2/sites-enabled/000-default.conf:21:	CustomLog ${APACHE_LOG_DIR}/access.log combined
    /etc/apache2/sites-available/000-default.conf:21:	CustomLog ${APACHE_LOG_DIR}/access.log combined
    /etc/apache2/sites-available/default-ssl.conf:13:	CustomLog ${APACHE_LOG_DIR}/access.log combined
    /etc/apache2/conf-available/other-vhosts-access-log.conf:2:CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log vhost_combined
    /etc/apache2/conf-enabled/other-vhosts-access-log.conf:2:CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log vhost_combined
    /etc/apache2/apache2.conf:126:HostnameLookups Off
    /etc/apache2/apache2.conf:212:LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
    /etc/apache2/apache2.conf:213:LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    /etc/apache2/apache2.conf:214:LogFormat "%h %l %u %t \"%r\" %>s %O" common
    /etc/apache2/apache2.conf:215:LogFormat "%{Referer}i -> %U" referer
    /etc/apache2/apache2.conf:216:LogFormat "%{User-agent}i" agent
  2. Create a backup copy of the file that contains the active CustomLog directive.
    $ sudo cp -a /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.bak

    Use the file path shown by the previous grep output when CustomLog is defined in a different virtual host file.

  3. Confirm that HostnameLookups is set to Off to avoid reverse DNS work during request logging.
    $ sudo grep -n '^[[:space:]]*HostnameLookups' /etc/apache2/apache2.conf
    126:HostnameLookups Off
  4. Add a lightweight LogFormat nickname near the existing LogFormat lines in /etc/apache2/apache2.conf.
    LogFormat "%a %t \"%r\" %>s %b" access_lite

    Appending %D at the end logs request time in microseconds when latency data is needed, at the cost of a slightly longer log line.

  5. Define dontlog rules for low-value requests in the same configuration context as the CustomLog directive.
    SetEnvIfNoCase Request_URI "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$" dontlog
    SetEnvIf Request_URI "^/healthz$" dontlog
    SetEnvIfNoCase User-Agent "^kube-probe/" dontlog

    If SetEnvIf triggers an “unknown directive” error, ensure mod_setenvif is loaded.

  6. Update the CustomLog directive to use the lightweight format with an env=!dontlog condition.
    CustomLog ${APACHE_LOG_DIR}/access.log access_lite env=!dontlog

    Keep the previous CustomLog line commented or in the backup file until the new log output is verified.

  7. Enable BufferedLogs once in the global server configuration to reduce log write frequency.
    BufferedLogs On

    BufferedLogs can improve I/O efficiency, but a crash can lose buffered entries, and the directive applies globally (not per-virtual-host).

  8. Test the Apache configuration for syntax errors.
    $ sudo apache2ctl configtest
  9. Reload the apache2 service to apply the new logging configuration.
    $ sudo systemctl reload apache2

    RHEL-family systems typically use sudo systemctl reload httpd.

  10. Send a request that should be logged.
    $ curl -I http://127.0.0.1/
    HTTP/1.1 200 OK
    Date: Sat, 10 Jan 2026 21:36:05 GMT
    Server: Apache/2.4.58 (Ubuntu)
    Last-Modified: Sat, 10 Jan 2026 21:15:28 GMT
    ETag: "29af-6480f24215cc8"
    Accept-Ranges: bytes
    Content-Length: 10671
    Vary: Accept-Encoding
    Content-Type: text/html
  11. Send a request that should be skipped by the dontlog rules.
    $ curl -I http://127.0.0.1/favicon.ico
    HTTP/1.1 404 Not Found
    Date: Sat, 10 Jan 2026 21:36:05 GMT
    Server: Apache/2.4.58 (Ubuntu)
    Content-Type: text/html; charset=iso-8859-1
  12. Check that the skipped path does not appear in /var/log/apache2/access.log.
    $ sudo bash -lc 'grep -F favicon.ico /var/log/apache2/access.log; echo $?'
    1
  13. Review the most recent access log line to confirm the new format is active.
    $ sudo tail -n 1 /var/log/apache2/access.log
    127.0.0.1 [11/Jan/2026:05:36:05 +0800] "GET / HTTP/1.0" 200 10671
  14. Optionally run ApacheBench against a representative endpoint to check throughput after the change.
    $ ab -n 2000 -c 200 http://127.0.0.1/
    This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
    ##### snipped #####
    Complete requests:      2000
    Failed requests:        0
    Requests per second:    19220.24 [#/sec] (mean)
    Time per request:       10.406 [ms] (mean)
    Time per request:       0.052 [ms] (mean, across all concurrent requests)
    Transfer rate:          205435.03 [Kbytes/sec] received

    Load tests can overwhelm a production origin; run from a controlled host and target a safe endpoint.

  15. Restore the backup virtual host configuration file when access logging must be reverted.
    $ sudo cp -a /etc/apache2/sites-available/000-default.conf.bak /etc/apache2/sites-available/000-default.conf
  16. Reload apache2 after restoring the backup configuration.
    $ sudo systemctl reload apache2