Facebook Pixel

Nginx Performance Tuning for Node.js Worker Processes, Caching, and Compression

Learn how to tune Nginx for maximum performance when serving Node.js applications configuring worker processes, gzip compression, caching, and connection limits.

Nginx Performance Tuning for Node.js

Optimizing Nginx can significantly improve your Node.js app's response time and throughput. This guide covers the key performance settings.

1. Worker Processes and Connections

Edit the main config:

sudo nano /etc/nginx/nginx.conf
worker_processes auto; # One worker per CPU core worker_connections 2048; # Connections per worker

worker_processes auto Nginx automatically creates one worker per CPU core. On a t2.micro (1 vCPU), you get 1 worker.

worker_connections Max connections each worker can handle. Default is 768. Increase to 2048 for higher traffic.

Total max clients = worker_processes × worker_connections = 1 × 2048 = 2048 concurrent connections.

2. Gzip Compression

gzip on; gzip_vary on; gzip_min_length 1000; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

gzip on Enable compression gzip_vary on Add Vary: Accept-Encoding header gzip_min_length 1000 Only compress responses > 1000 bytes gzip_comp_level 6 Compression level (1-9, 6 is a good balance) gzip_types Which MIME types to compress

Compression reduces bandwidth by 60-80% for text-based responses.

3. Static File Caching

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; }

expires 1y Browser caches for 1 year immutable Browser never revalidates (hashed file names ensure new versions get new URLs) access_log off Don't log static file requests (reduces disk I/O)

4. Proxy Buffering

location / { proxy_pass http://localhost:3000; proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; # ... other proxy headers ... }

proxy_buffering on Nginx buffers the response from Node.js before sending to the client. This frees Node.js to handle other requests.

proxy_buffers 8 4k 8 buffers of 4 KB each for response data.

proxy_busy_buffers_size Buffers used for the first part of the response.

5. Connection Limits

limit_conn_zone $binary_remote_addr zone=conn_limit:10m; server { limit_conn conn_limit 10; # Max 10 concurrent connections per IP location / { proxy_pass http://localhost:3000; } }

This limits each IP to 10 concurrent connections, preventing abuse.

6. Rate Limiting

limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; server { location /api/ { limit_req zone=req_limit burst=20 nodelay; proxy_pass http://localhost:3000; } }

rate=10r/s 10 requests per second per IP burst=20 Allow bursts of up to 20 requests nodelay Serve burst requests immediately (not delayed)

7. Keep-Alive Connections

keepalive_timeout 65; keepalive_requests 100;

keepalive_timeout How long to keep the connection open (seconds) keepalive_requests Max requests per keep-alive connection

Keep-alive reduces the overhead of establishing new TCP connections.

8. Upstream Keep-Alive

upstream nodejs_backend { server 127.0.0.1:3000; keepalive 32; } server { location / { proxy_pass http://nodejs_backend; proxy_http_version 1.1; proxy_set_header Connection ""; } }

This keeps 32 connections open between Nginx and Node.js, reducing connection overhead.

9. Timeouts

client_body_timeout 12; client_header_timeout 12; send_timeout 10; keepalive_timeout 65; location / { proxy_connect_timeout 5; proxy_send_timeout 30; proxy_read_timeout 30; }

Shorter client timeouts protect against slowloris attacks. Proxy timeouts should be long enough for your slowest API endpoint.

10. File Descriptor Limits

# Check current limits ulimit -n # 1024 # Increase for Nginx sudo nano /etc/nginx/nginx.conf
worker_rlimit_nofile 65535;

Also increase the system limit:

sudo nano /etc/security/limits.conf # Add: # * soft nofile 65535 # * hard nofile 65535

The Takeaway

Nginx performance tuning involves: setting worker_processes to auto and worker_connections to 2048, enabling gzip compression (level 6, text types only), caching static files for 1 year with immutable, proxy buffering to free Node.js, rate limiting to protect against abuse, keep-alive connections for efficiency, appropriate timeouts, and increasing file descriptor limits. Test before and after to measure improvements.

Set worker_processes auto (one per CPU core) and worker_connections 2048 in nginx.conf. Total max clients = worker_processes × worker_connections. On a t2.micro with 1 vCPU, you get 1 worker × 2048 = 2048 concurrent connections.

Set gzip on, gzip_comp_level 6, gzip_min_length 1000, gzip_types for text-based MIME types (text/plain, text/css, application/json, application/javascript). Add gzip_vary on for the Vary header. This reduces bandwidth by 60-80%.

Add a location block matching static file extensions (js, css, png, jpg, etc.) with expires 1y, add_header Cache-Control 'public, immutable', and access_log off. Hashed file names from build tools ensure new versions get new URLs.

Define limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s in the http block. Then add limit_req zone=req_limit burst=20 nodelay in the location block. This allows 10 requests per second per IP with a burst of 20.

Proxy buffering (proxy_buffering on) makes Nginx buffer the response from Node.js before sending to the client. This frees Node.js to handle other requests. Set proxy_buffer_size 4k and proxy_buffers 8 4k for typical API responses.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.