High-traffic Nginx instances can spend surprising time on access logging, especially when each request produces a log write and the disk is already busy. Reducing access log overhead lowers tail latency, frees I/O headroom for responses, and helps prevent log-induced stalls during traffic spikes.

Access logging is controlled by the access_log directive and formatted by log_format inside the http, server, or location contexts. Each worker appends a formatted line to the configured log target, so high request rates translate into frequent string formatting and file writes; buffering and conditional logging reduce the number of syscalls and the number of lines written.

Buffering improves throughput by batching writes, but it introduces a short delay before entries appear and risks losing the most recent buffered lines during a crash or hard reboot. Disabling or filtering logs can also impact auditing, security investigations, and rate-limit troubleshooting, so filters should target noise (static assets, health checks) while preserving meaningful application requests.

Steps to optimize Nginx access log performance:

  1. Locate existing access_log, log_format, and open_log_file_cache directives to avoid duplicate access logs.
    $ sudo grep -RIn --include='*.conf' -E '^\s*(access_log|log_format|open_log_file_cache)\b' /etc/nginx
    /etc/nginx/nginx.conf:35:    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    /etc/nginx/nginx.conf:41:                    '$status $body_bytes_sent "$http_referer" '
    /etc/nginx/nginx.conf:42:                    '"$http_user_agent"';
    /etc/nginx/nginx.conf:44:    access_log /var/log/nginx/access.log main;

    Multiple access_log directives in the same context write multiple logs and increase overhead.

  2. Open the primary configuration file for editing.
    $ sudoedit /etc/nginx/nginx.conf
  3. Insert the following map block inside the http context to disable logging for common noise paths.
    map $uri $log_request {
        default 1;
        =/favicon.ico 0;
        =/robots.txt 0;
        ~* \.(?:css|js|map|jpg|jpeg|png|gif|ico|svg|webp|woff2?)$ 0;
    }

    A location-scoped override like location = /healthz { access_log off; } also works for exact endpoints.

  4. Add a performance-focused log_format inside the http context to reduce log line size.
    log_format main_perf '$remote_addr - [$time_local] "$request" '
                         '$status $body_bytes_sent $request_time';

    Add fields like "$http_user_agent" only when they are operationally required.

  5. Replace the primary access_log directive with a buffered, conditional variant using main_perf with $log_request.
    access_log /var/log/nginx/access.log main_perf buffer=64k flush=1s if=$log_request;

    Buffered logging can drop the most recent entries during a crash or hard reboot; lower flush= reduces loss at the cost of more writes.

  6. Enable open_log_file_cache inside the http context when the access_log path contains variables like $host.
    open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

    Skip this directive when log files are static (for example, /var/log/nginx/access.log) because the descriptor is already kept open.

  7. Validate the updated Nginx configuration syntax.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  8. Reload Nginx to apply the logging changes.
    $ sudo systemctl reload nginx
  9. Generate a request that should be logged.
    $ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
    200
  10. Generate a request that should be suppressed by $log_request.
    $ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/favicon.ico
    404

    With flush=1s, new entries appear after the flush interval or when the buffer fills.

  11. Inspect the newest entry in /var/log/nginx/access.log for the expected logged request.
    $ sudo tail -n 1 /var/log/nginx/access.log
    127.0.0.1 - [14/Dec/2025:13:37:20 +0000] "GET / HTTP/1.1" 200 612 0.002
  12. Search /var/log/nginx/access.log for a suppressed /favicon.ico entry.
    $ sudo grep -F '"GET /favicon.ico' /var/log/nginx/access.log

    No output indicates the request was suppressed from access logging.

Discuss the article:

Comment anonymously. Login not required.