When working with Nginx as a reverse proxy for Python applications (particularly with Gunicorn), we often encounter a specific challenge with large responses. The default configuration triggers warnings like:
an upstream response is buffered to a temporary file
/path/to/nginx/proxy_temp/4/86/0000000864 while reading upstream,
client: 1.2.3.4, server: api.ourdomain.com, request: "GET /pdf/..."
Nginx uses a sophisticated buffering system with these key components:
proxy_buffer_size
: Default 4K/8K (usually one memory page)proxy_buffers
: Number and size of buffers (default 8 buffers of proxy_buffer_size)proxy_max_temp_file_size
: Controls temp file usage (default 1GB)proxy_busy_buffers_size
: Controls when buffers are flushed to client
Instead of the problematic approaches mentioned in the original question, consider these production-tested solutions:
1. Selective Buffer Configuration
Configure different buffer settings for specific locations:
location /small_responses {
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}
location /large_files {
proxy_buffer_size 8k;
proxy_buffers 16 8k;
proxy_busy_buffers_size 16k;
proxy_max_temp_file_size 1024m;
}
2. Adjusting Log Levels
The most elegant solution is to change the log level for these specific messages:
http {
# Set main error log level
error_log /var/log/nginx/error.log warn;
# Change specific message to notice level
map $upstream_http_content_length $loggable {
default 1;
"~^[0-9]{5,}" 0; # Skip logging for responses > 9999 bytes
}
server {
error_log /var/log/nginx/server_error.log warn;
if ($loggable = 0) {
access_log off;
}
}
}
3. Optimizing Temporary File Handling
For better performance with large files:
proxy_temp_path /var/cache/nginx/temp levels=1:2 keys_zone=temp_zone:10m inactive=1d max_size=10g;
When implementing these solutions, keep in mind:
- Memory usage vs. disk I/O tradeoffs
- Impact on slow clients (especially for large PDFs)
- Worker process efficiency
- Overall system resource utilization
- Monitor buffer usage with Nginx metrics
- Implement proper caching for large, static-like responses
- Consider using X-Accel-Redirect for very large files
- Regularly rotate and analyze proxy_temp files
When working with Nginx as a reverse proxy (particularly for Python applications using Gunicorn), we often encounter this log spam:
an upstream response is buffered to a temporary file
/path/to/nginx/proxy_temp/4/86/0000000864 while reading upstream,
client: 1.2.3.4, server: api.example.com, request: "GET /pdf/..."
This occurs when responses exceed the default buffer size (typically 4K or 8K). While technically a "warning", it's actually Nginx working as designed - just being overly verbose about it.
Contrary to what the warning suggests, temporary file buffering is a feature - not a failure. It prevents slow clients from tying up backend workers. For PDF generation endpoints that produce 1-2MB responses, this is exactly what we want.
Instead of disabling buffering (which would be dangerous), we should tune the parameters:
# In nginx.conf or your server block
proxy_buffering on;
proxy_buffer_size 8k; # Header buffer
proxy_buffers 8 8k; # Number and size of buffers
proxy_busy_buffers_size 16k;
proxy_temp_path /var/nginx/proxy_temp;
The most elegant solution is to modify the log level for these specific messages:
error_log /var/log/nginx/error.log warn;
error_log /var/log/nginx/buffering.log notice;
Then in your location block handling large responses:
location /pdf/ {
proxy_pass http://gunicorn_backend;
proxy_temp_file_write_size 1m;
log_subrequest on;
access_log off;
error_log /var/log/nginx/buffering.log notice;
}
The key metrics to monitor are:
- proxy_temp directory usage (df -h /var/nginx)
- I/O wait during peak PDF generation periods (iostat -x 1)
- Gunicorn worker utilization during slow client scenarios
For mixed-size endpoints, consider this pattern:
map $sent_http_content_length $should_buffer {
default "on";
~^[0-9]{1,5}$ "off"; # Files under 100KB
}
server {
proxy_buffering $should_buffer;
# ...
}