The sendfile directive in Nginx enables the operating system’s sendfile() system call to transfer files directly from disk to network socket without copying data through user space. This zero-copy mechanism reduces CPU overhead and improves throughput when serving static content such as images, CSS files, JavaScript, videos, and downloadable files. For high-traffic sites that serve substantial static assets, enabling sendfile can noticeably reduce server load.
By default, Nginx has sendfile disabled. This guide explains how to enable the directive, configure related optimizations like tcp_nopush and sendfile_max_chunk, and understand when sendfile may not be appropriate. The configuration applies to any Linux or Unix-like system running Nginx.
What Is the 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.
According to the official Nginx documentation, the directive can be applied at the http, server, location, and if in location levels, giving you fine-grained control over which content uses zero-copy transfer.
Enable Sendfile in Nginx
First, create a backup of your configuration file in case you need to revert changes:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Next, open the main configuration file. On most distributions, this file is located at /etc/nginx/nginx.conf:
sudo nano /etc/nginx/nginx.conf
Locate the http block and add or modify the sendfile directive. For optimal performance, 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
}
The tcp_nopush directive enables the TCP_CORK socket option on Linux (or TCP_NOPUSH on FreeBSD), which tells the kernel to delay sending packets until the buffer is full or the connection is closed. Combined with sendfile, this reduces the number of packets sent and improves network efficiency.
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
}
The example above 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 (like 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://backend;
}
}
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.
Test and Apply the Configuration
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:
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.
When Sendfile May Not Work Correctly
While sendfile improves performance in most static file serving scenarios, certain situations can cause unexpected behavior or require you to disable it:
Network-mounted filesystems (NFS, CIFS, SMB)
- The sendfile system call may not work correctly or may perform poorly with network filesystems
- Some NFS implementations return incorrect file sizes or have caching issues that cause truncated responses
- If you serve files from NFS mounts and experience corrupted or incomplete downloads, disable sendfile for those locations
Files that change during transfer
- If a file is modified while sendfile is transferring it, the client may receive a mix of old and new content
- This is rare for typical web assets but can occur with log files or dynamically generated content written directly to the filesystem
Proxied or dynamically generated responses
- Sendfile only applies to files Nginx reads directly from disk
- Responses from
proxy_pass,fastcgi_pass, or other upstream handlers are unaffected by the sendfile directive
If you encounter issues with specific content, disable sendfile for the affected location rather than globally:
location /nfs-content/ {
sendfile off;
alias /mnt/nfs/share/;
}
Sendfile works well alongside other Nginx performance features. Consider enabling these related optimizations for static content delivery:
- 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
These directives complement sendfile by addressing different aspects of request handling and response delivery.
Conclusion
The sendfile directive enables zero-copy file transfers, reducing CPU overhead when serving static content. Combined with tcp_nopush and sendfile_max_chunk, this configuration optimizes static file delivery while preventing any single connection from monopolizing worker processes. For NFS or similar network filesystems, disable sendfile at the location level to avoid transfer issues.