Busy Nginx servers can spend measurable CPU time and disk I/O budget on access logging, especially when every image, stylesheet, health check, and cache hit generates a separate line. Reducing low-value access log writes lowers per-request work while preserving the entries operators still need for application, audit, and latency review.
The ngx_http_log_module formats requests with log_format and writes them through access_log in the http, server, or location context where processing ends. Performance gains usually come from logging fewer static or health-check requests, shortening each line, and buffering writes so workers do fewer disk operations.
Buffered logging changes how quickly entries appear on disk, and a crash can lose the newest buffered lines before they flush. When a log path contains variables such as $host, buffered writes do not apply and open_log_file_cache only reduces repeated open and close work for frequently used log files, so keep the filter focused on traffic that has no troubleshooting or security value.
Related: How to improve Nginx performance
Related: How to configure log rotation for Nginx
Steps to optimize Nginx access log performance:
- Print the active Nginx configuration and note the existing access_log, log_format, and open_log_file_cache directives before editing.
$ sudo nginx -T nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ##### snipped ##### http { access_log /var/log/nginx/access.log; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } ##### snipped #####Multiple access_log directives on the same configuration level write multiple log entries for each request. Replace the active directive instead of adding a second log at the same level.
- Open the Nginx configuration file that controls access logging at the http level.
$ sudoedit /etc/nginx/nginx.conf
On packaged layouts that include /etc/nginx/conf.d/ from the http block, a dedicated snippet such as /etc/nginx/conf.d/logging-performance.conf keeps the tuning separate from virtual host files.
- Insert a map block inside the http context to suppress known low-value paths before Nginx reaches the log write.
map $uri $log_request { default 1; =/favicon.ico 0; =/robots.txt 0; ~*\.(css|js|map|jpg|jpeg|png|gif|ico|svg|webp|woff|woff2)$ 0; }Using map keeps the logging condition centralized and cheap to evaluate for every request.
- Define a shorter log_format inside the http context so each retained request writes fewer bytes.
log_format main_perf '$remote_addr - [$time_local] "$request" ' '$status $body_bytes_sent $request_time';Add fields such as "$http_user_agent" or "$http_referer" only when they are operationally necessary.
- Replace the primary access_log directive with a buffered conditional write that uses main_perf and $log_request.
access_log /var/log/nginx/access.log main_perf buffer=64k flush=1s if=$log_request;
Buffered logging delays writes and can lose the newest lines during a crash or hard reboot.
Use access_log off; only on exact location blocks whose requests have no audit or troubleshooting value.
- Enable open_log_file_cache only when the log path itself contains variables such as $host or $server_name.
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
Static paths such as /var/log/nginx/access.log already stay open, so this directive is for variable-based log filenames.
- Test the updated Nginx configuration before reloading the service.
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Related: How to test Nginx configuration
- Reload Nginx so workers start using the new logging rules.
$ sudo systemctl reload nginx
Related: How to manage the Nginx service
- Send a unique request that should still be written to the access log.
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/sg-log-test-request 404The HTTP status does not matter for this check. The path has no suppressed asset extension, so it should be logged.
- Send a unique asset-style request that the $log_request map should suppress from access logging.
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/sg-log-test.png 404 - Wait longer than the configured flush interval before reading the log on a quiet server.
$ sleep 2
Buffered log data is written when the buffer fills, when the flush timer expires, or when workers reopen or shut down the log file.
- Search /var/log/nginx/access.log for the retained test request and confirm the shortened format includes $request_time.
$ sudo grep -F '"GET /sg-log-test-request' /var/log/nginx/access.log 127.0.0.1 - [06/Jun/2026:11:34:50 +0000] "GET /sg-log-test-request HTTP/1.1" 404 162 0.000
- Search /var/log/nginx/access.log for the suppressed asset-style request.
$ sudo grep -F '"GET /sg-log-test.png' /var/log/nginx/access.log
No output means the request matched $log_request = 0 and was filtered out before Nginx wrote the access log entry.
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.