Nginx Configuration Patterns for Node.js Applications: Proxy vs Streaming
DevOpsnginx

Nginx Configuration Patterns for Node.js Applications: Proxy vs Streaming

Ihor ChyshkalaIhor Chyshkala

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:

  1. WebSocket Support: Full configuration for WebSocket connections
  2. Extended Timeouts: 300-second timeouts for long-running operations
  3. Headers Configuration: Complete set of forwarded headers for proper request handling
  4. Static Asset Caching: Separate location block for optimized static content delivery
  5. 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:

  1. Connection Pooling: Uses keepalive connections to improve performance
  2. Security Headers: Additional security-focused headers
  3. Optimized Timeouts: Shorter 60-second timeouts for better resource management
  4. Header Cleanup: Removes potentially sensitive headers
  5. 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:

  1. Application Type
    • Standard Proxy: Modern web applications, SPAs
    • Streaming: Real-time data, APIs, streaming services
  2. Resource Constraints
    • Standard Proxy: More resource-intensive
    • Streaming: More efficient resource usage
  3. Security Requirements
    • Standard Proxy: Basic security
    • Streaming: Enhanced security headers
  4. 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.

About the Author

Ihor Chyshkala

Ihor Chyshkala

Code Alchemist: Transmuting Ideas into Reality with JS & PHP. DevOps Wizard: Transforming Infrastructure into Cloud Gold | Orchestrating CI/CD Magic | Crafting Automation Elixirs