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. Tightening access logging reduces per-request overhead and leaves more headroom for application responses during sustained traffic.
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 low-value 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 change focused on genuinely noisy traffic instead of weakening application or security visibility everywhere.
Related: How to improve Nginx performance
Related: How to configure log rotation for Nginx
$ sudo nginx -T 2>/dev/null | grep -nE '^\s*(access_log|log_format|open_log_file_cache)\b' 42: access_log /var/log/nginx/access.log; 119: log_format combined '$remote_addr - $remote_user [$time_local] '
Multiple access_log directives on the same configuration level write multiple log entries for each request.
$ 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.
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.
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.
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.
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.
$ 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
$ sudo systemctl reload nginx
Related: How to manage the Nginx service
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
200
$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/favicon.ico
404
$ 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.
$ sudo tail -n 1 /var/log/nginx/access.log 127.0.0.1 - [09/Apr/2026:13:10:01 +0000] "GET / HTTP/1.1" 200 896 0.000
$ sudo grep -F '"GET /favicon.ico' /var/log/nginx/access.log
No output means the request was filtered out before Nginx wrote the access log entry.