Large static-file responses can make Nginx spend CPU time copying data it does not need to inspect. To enable sendfile in Nginx, set the sendfile directive so direct file transfers use the operating system’s zero-copy path instead of copying images, CSS, JavaScript, videos, or downloads through user space first.
The documented default for the Nginx sendfile directive is off, though many packaged configuration templates already set sendfile on;. Check the active parsed configuration before adding another directive. Most static-heavy sites place it in the http block, pair it with tcp_nopush, and override it only where network storage, directio, changing files, or upstream-generated responses need different handling.
Nginx Sendfile Defaults and Contexts
The documented Nginx sendfile directive default is off. The final value that matters is the inherited value in the active http, server, or location context that serves the file.
| Directive | Default | Context | What to know |
|---|---|---|---|
sendfile | off | http, server, location, if in location | Enables or disables sendfile() for files Nginx reads directly from disk. |
sendfile_max_chunk | 2m | http, server, location | Limits how much data one sendfile() call can transfer. Before Nginx 1.21.4, there was no default limit. |
tcp_nopush | off | http, server, location | Uses TCP_NOPUSH on FreeBSD or TCP_CORK on Linux, but only when sendfile is also used. |
tcp_nodelay | on | http, server, location | Separate keepalive and low-latency socket behavior. It is not required to enable sendfile. |
directio | off | http, server, location | Available since Nginx 0.7.7. Enables direct I/O for files at or above the configured size and disables sendfile for that request. |
Nginx HTTP core module documentation does not define an ssl_sendfile directive. If you see SSL_sendfile() in kernel TLS discussions, treat it as implementation terminology, not a directive to add to nginx.conf.
Enable Sendfile in Nginx
Check the Active Sendfile Setting
Before editing, inspect the configuration Nginx actually parses. This filter prints the owning # configuration file line before any matching sendfile, tcp_nopush, sendfile_max_chunk, or directio directive.
sudo nginx -T 2>/dev/null | awk '
/^# configuration file / { file=$0; next }
/^[[:space:]]*(sendfile|tcp_nopush|sendfile_max_chunk|directio)[[:space:]]+/ {
if (file != shown) {
print file
shown=file
}
print
}'
Relevant output may show a packaged default similar to this:
# configuration file /etc/nginx/nginx.conf:
sendfile on;
If no sendfile line appears, the documented default remains off for that scope unless a broader context sets it. If the directive appears in an included server or location file, edit that owning file instead of adding a duplicate value elsewhere.
Choose the Sendfile Scope
Placement controls how widely the directive applies. A broad http value works for most static-file servers, while server and location values keep exceptions close to the virtual host or path that needs them.
| Placement | Best fit | Risk to check |
|---|---|---|
http | Most sites that serve static assets from local disk. | Every virtual host inherits the value unless it overrides it later. |
server | One virtual host serves static files differently from the rest. | All matching locations in that server inherit the value. |
location | Only one URI path, such as downloads, media, or a mounted share, needs different behavior. | Location matching must route the intended files to that block. |
Edit the Nginx Configuration
First, create a backup of the file you will edit in case you need to revert changes. For the main configuration file, use:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Open the owning configuration file. The main file is usually /etc/nginx/nginx.conf, but an included server or location file should be backed up and edited when the active-config check points there.
sudo nano /etc/nginx/nginx.conf
Locate the http block and add or modify the sendfile directive. For static-file delivery, you can also enable tcp_nopush, which works together with sendfile to send response headers and the beginning of a file in one packet:
http {
sendfile on;
tcp_nopush on;
# Other directives can stay here
}
The tcp_nopush directive enables the TCP_CORK socket option on Linux or TCP_NOPUSH on FreeBSD. With sendfile, it lets Nginx send the response header and the beginning of a file in one packet, then prefer full packets for the file body.
Tune Nginx Sendfile Behavior for Production
Limit Data Per Sendfile Call
When serving large files, a single sendfile() call can transfer substantial amounts of data. Without limits, one fast connection downloading a large file could monopolize a worker process, delaying responses to other clients. The sendfile_max_chunk directive prevents this by limiting how much data transfers in each call:
http {
sendfile on;
tcp_nopush on;
sendfile_max_chunk 2m;
# Other directives can stay here
}
This configuration limits each sendfile call to 2 megabytes. The default is 2m as of Nginx 1.21.4, but older versions had no limit. For servers handling many concurrent downloads of large files, a smaller chunk size, such as 512k or 1m, can improve fairness across connections.
Apply Sendfile to Specific Locations
You can enable sendfile globally in the http block or selectively within server or location blocks. For example, to enable sendfile only for a static assets directory while keeping it off elsewhere:
server {
listen 80;
server_name example.com;
# Sendfile disabled by default for this server
sendfile off;
location /static/ {
# Enable sendfile for static assets
sendfile on;
tcp_nopush on;
alias /var/www/example.com/static/;
}
location / {
# Dynamic content handled by upstream
proxy_pass http://127.0.0.1:8080;
}
}
This selective approach is useful when your server handles both static files and proxied dynamic content. Sendfile only benefits direct file serving; it has no effect on proxied responses. If the URI prefix and filesystem path do not line up cleanly, review Nginx root versus alias behavior before testing sendfile.
Test, Reload, and Verify Nginx After Sendfile Changes
After saving your changes, test the configuration for syntax errors before applying:
sudo nginx -t
A successful test produces output confirming the configuration is valid:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
If the test passes, reload Nginx to apply the changes without dropping existing connections. On systemd-based distributions, use:
sudo systemctl reload nginx
Using
reloadinstead ofrestartis preferred for configuration changes. A reload gracefully applies the new configuration while allowing existing connections to complete, avoiding service interruption.
Confirm that Nginx still answers locally after the reload:
curl --noproxy '*' -sSI http://127.0.0.1/ | sed -n '1p'
A healthy default HTTP listener returns a status line such as:
HTTP/1.1 200 OK
For name-based sites, repeat the check with the matching host header and a known static asset path. A redirect, 403, or 404 can still prove Nginx answered, but it does not prove the intended static-file location handled the request.
curl --noproxy '*' -H 'Host: example.com' -sSI http://127.0.0.1/static/app.css | sed -n '1p'
Understand the Nginx Sendfile System Call
When Nginx serves a static file without sendfile, the process involves multiple steps: the kernel reads file data into a buffer, copies it to the Nginx process in user space, and Nginx then writes it to the socket back through the kernel. This double-copying consumes CPU cycles and memory bandwidth.
With sendfile enabled, Nginx instructs the kernel to transfer data directly from the file descriptor to the socket descriptor. The data never enters user space, which eliminates the copy overhead. This optimization matters most when serving many concurrent requests for static files, as it frees CPU resources for other tasks.
The directive is usually configured at the http level when a server mostly delivers static assets. You can still override it in a narrower server or location block when one path needs different behavior.
Roll Back Sendfile Changes
Restore the backup if the syntax test fails, a static-file path behaves incorrectly, or the change affects more sites than intended. For the main configuration file example, use the backup that matches the file you edited and replace the reload command with your service-manager equivalent on non-systemd systems.
sudo cp /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf
sudo nginx -t
sudo systemctl reload nginx
Troubleshoot Nginx Sendfile Issues
Sendfile is usually safe for local static assets, but a few configurations need a narrower override. Start by identifying whether Nginx is serving a real file from disk, then disable sendfile only for the affected location when the symptom matches one of these cases.
Unknown ssl_sendfile Directive
Nginx does not provide an ssl_sendfile directive in the HTTP core module. If sudo nginx -t reports unknown directive "ssl_sendfile", remove that line and use the normal sendfile directive only where Nginx serves files directly from disk.
# Wrong
# ssl_sendfile on;
# Correct
sendfile on;
After removing the unsupported directive, repeat sudo nginx -t and reload only after the syntax test succeeds.
Incomplete Downloads from Network Filesystems
Network filesystems such as NFS, CIFS, and SMB can expose file-size or caching behavior that does not match a local disk. If users report corrupted, truncated, or inconsistent downloads from a mounted share, disable sendfile for that path and retest the same file.
location /nfs-content/ {
sendfile off;
alias /mnt/nfs/share/;
}
Directio Disables Nginx Sendfile for Matching Files
The directio directive is useful for large-file serving and AIO workflows, but it automatically disables sendfile for the request that meets the configured size. For example, on Linux with AIO enabled, this location uses sendfile below 8 MB and switches to the directio path for files at or above 8 MB:
location /video/ {
sendfile on;
aio on;
directio 8m;
}
If your goal is to keep sendfile active for all files in a static location, leave directio off there. If your goal is large-file direct I/O, keep the directive and understand that those larger requests are intentionally not using sendfile.
Changing Files During Sendfile Transfers
If an application rewrites a file while Nginx is transferring it, the client can receive inconsistent content. This is uncommon for versioned assets, but it can happen with log exports, generated archives, or files that are written in place. Write generated files to a temporary name, move them into place atomically, or disable sendfile for that location.
No Sendfile Effect on Proxied or Generated Responses
Sendfile only applies when Nginx reads a file and sends it directly. Responses from proxy_pass, fastcgi_pass, and similar upstream handlers are generated elsewhere, so the directive does not accelerate those responses. Keep sendfile decisions focused on static-file locations and handle upstream performance with buffering, caching, or application tuning instead.
After any troubleshooting change, repeat the syntax test and reload sequence. On non-systemd systems, use the equivalent service reload command:
sudo nginx -t
sudo systemctl reload nginx
Related Nginx Performance Optimizations
Sendfile works well alongside other Nginx performance features, but each directive solves a different part of request handling. When the bottleneck is file metadata lookup, compression, connection setup, or worker distribution rather than the file-transfer path itself, these related topics are better next steps:
- Enable Open File Cache in Nginx to cache file descriptors and reduce disk I/O
- Enable Gzip Compression in Nginx to reduce bandwidth for compressible content
- Enable TCP Fast Open in Nginx to reduce connection establishment latency
- Enable Reuseport in Nginx to improve load distribution across worker processes
Gzip compression and sendfile can coexist, but they are not the same optimization. Sendfile applies to direct file transfers from disk, while gzip reduces response size for compressible content and may use a different output path depending on buffering and content handling.
Conclusion
Nginx is now configured to use sendfile where it helps direct static-file delivery, with tcp_nopush and sendfile_max_chunk controlling packet behavior and worker fairness. Keep directio, network filesystems, changing files, and upstream-generated responses out of the default path unless you have tested them for the affected location. If static delivery still bottlenecks, check file metadata caching, compression, or connection-level tuning next.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>