Nginx Configuration Patterns for Node.js Applications: Proxy vs Streaming
When setting up Nginx as a reverse proxy for Node.js applications, there are different configuration patterns we can use depending on our specific needs. In this article, we'll compare two popular approaches: standard proxy configuration and streaming-optimized configuration.
Standard Proxy Configuration for Modern Node.js Apps
This configuration is commonly used with frameworks like Next.js, Nuxt.js, or similar modern Node.js applications:
# Main application proxy configuration
location / {
# Rate limiting configuration
limit_req zone=app_limit burst=50 nodelay;
# Proxy settings
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# WebSocket configuration
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
# Static assets configuration
location /_assets/ {
expires 1y;
add_header Cache-Control "public, no-transform";
proxy_pass http://127.0.0.1:3000/_assets/;
access_log off;
}
Key Features:
- WebSocket Support: Full configuration for WebSocket connections
- Extended Timeouts: 300-second timeouts for long-running operations
- Headers Configuration: Complete set of forwarded headers for proper request handling
- Static Asset Caching: Separate location block for optimized static content delivery
- Rate Limiting: Basic protection against overload
Streaming-Optimized Configuration
This configuration is optimized for applications that handle streaming data or require high-performance proxying:
# Upstream definition for load balancing
upstream backend_servers {
server localhost:3000;
keepalive 32;
}
location / {
proxy_pass http://backend_servers;
# Essential proxy headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# Security headers
proxy_set_header X-Script-Name "";
proxy_hide_header X-Powered-By;
proxy_hide_header X-Runtime;
# Optimized timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
}
Key Features:
- Connection Pooling: Uses keepalive connections to improve performance
- Security Headers: Additional security-focused headers
- Optimized Timeouts: Shorter 60-second timeouts for better resource management
- Header Cleanup: Removes potentially sensitive headers
- Upstream Configuration: Ready for load balancing
Comparing the Approaches
Standard Proxy Configuration
Pros:
- Better suited for modern JavaScript frameworks
- Optimized for static content
- WebSocket-friendly
- Longer timeouts for complex operations
- Built-in rate limiting
Cons:
- Higher resource usage due to longer timeouts
- Less emphasis on security headers
- May not be optimal for high-throughput scenarios
Streaming Configuration
Pros:
- Better performance for streaming data
- Enhanced security headers
- Connection pooling
- More efficient resource usage
- Ready for load balancing
Cons:
- Less optimized for static content
- Shorter timeouts might not suit all use cases
- Requires more manual security configuration
Performance Considerations
Standard Proxy
# Performance optimizations for standard proxy
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 8k;
proxy_busy_buffers_size 16k;
Streaming Configuration
# Performance optimizations for streaming
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
Security Enhancements
Both configurations can benefit from additional security measures:
# Common security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Request size limits
client_max_body_size 10M;
client_body_buffer_size 128k;
Load Balancing Considerations
For high-traffic applications, consider adding load balancing:
upstream backend {
least_conn; # Load balancing algorithm
server localhost:3000;
server localhost:3001;
keepalive 32;
}
SSL Configuration
Both configurations should include proper SSL settings:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
Choosing the Right Configuration
Consider these factors when choosing between configurations:
- Application Type
- Standard Proxy: Modern web applications, SPAs
- Streaming: Real-time data, APIs, streaming services
- Resource Constraints
- Standard Proxy: More resource-intensive
- Streaming: More efficient resource usage
- Security Requirements
- Standard Proxy: Basic security
- Streaming: Enhanced security headers
- Traffic Patterns
- Standard Proxy: Mixed content, WebSocket
- Streaming: High-throughput, real-time data
Conclusion
Both configurations have their place in modern web architecture:
- Use the Standard Proxy Configuration when:
- Building modern web applications
- Dealing with static assets
- Requiring WebSocket support
- Working with longer operations
- Use the Streaming Configuration when:
- Handling real-time data
- Requiring high performance
- Dealing with microservices
- Implementing load balancing
Remember to adjust these configurations based on your specific needs, monitoring results, and performance requirements.