Worker Tuning and Production Tips

Introduction

Default Nginx settings work for learning and small VPS hosts. As traffic grows, worker processes, connections, and keepalive tuning matter—along with how you organize config files for safe deploys. This chapter covers practical production defaults and team habits without premature micro-optimization.

Prerequisites

worker_processes and worker_connections

In /etc/nginx/nginx.conf:

nginx
user www-data;
worker_processes auto;
pid /run/nginx.pid;
 
events {
    worker_connections 768;
    multi_accept on;
}

Code explanation:

  • worker_processes auto — one worker per CPU core (typical)
  • worker_connections — max simultaneous connections per worker
  • Rough max clients ≈ workers × connections (shared with upstream keepalive)

Raise cautiously on busy servers:

nginx
events {
    worker_connections 2048;
}

Also ensure ulimit -n (open files) is high enough in systemd unit or /etc/security/limits.conf.

Keepalive for Clients

nginx
http {
    keepalive_timeout 65;
    keepalive_requests 1000;
}

Code explanation:

  • Reuses TCP connections for browser HTTP/1.1
  • Lower timeout frees resources on quiet sites; raise for high-traffic APIs rarely needed at edge

sendfile and TCP (Usually Default)

nginx
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}

Already enabled on many distros—verify before duplicating. Helps static file throughput.

open_file_cache (Static Heavy Sites)

nginx
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Caches file descriptors for frequently served static assets—optional on large static CDNs at origin.

Config Organization

One site per file

text
/etc/nginx/
├── nginx.conf
├── proxy_params
├── sites-available/
│   ├── api.example.com
│   └── www.example.com
└── sites-enabled/
    └── api.example.com -> ../sites-available/api.example.com

Shared snippets

nginx
include /etc/nginx/proxy_params;
include /etc/letsencrypt/options-ssl-nginx.conf;

Never commit privkey.pem or .htpasswd to Git—deploy via secure paths on server.

Environment-specific includes

nginx
include /etc/nginx/conf.d/*.conf;

Staging vs production: separate files on each host, not commented blocks in one mega-file.

Deploy Workflow

  1. Edit config in sites-available
  2. sudo nginx -t
  3. sudo systemctl reload nginx
  4. curl -I smoke test
  5. Watch error.log for 60 seconds

Keep previous config backup:

bash
sudo cp /etc/nginx/sites-available/api /etc/nginx/sites-available/api.bak.$(date +%F)

Secrets and Keys

  • TLS keys in /etc/letsencrypt/ — root-readable
  • API keys belong in app env—not Nginx config in repo
  • Use env file on server + systemd for Spring Boot / Node

Capacity Planning (Rule of Thumb)

SignalAction
High CPU on nginx workersCheck gzip level, SSL, traffic volume; scale VPS or add CDN
Many 502/504Fix upstream; tune timeouts
worker_connections errors in logRaise limit + ulimit
Disk IO waitLog rotation, access_log volume, static on CDN

Measure with htop, access log rates, and APM on backends before tuning obscure directives.

X-Accel-Redirect (Awareness)

Nginx serves large files efficiently after app authorizes download:

nginx
location /protected-files/ {
    internal;
    alias /data/downloads/;
}

App returns header X-Accel-Redirect: /protected-files/report.pdf—advanced pattern for file platforms.

Production Checklist

  • server_tokens off
  • HTTPS with auto-renewal
  • Separate logs per major site
  • nginx -t in CI or deploy script for config templates
  • Firewall: 80/443 public; app ports localhost only
  • Rate limits on auth endpoints
  • Backups of config in /etc/nginx

FAQ

worker_processes 1 for debug?

Yes on tiny VM—auto is normal in production.

Should I run multiple Nginx instances?

One per host is standard—scale horizontally with more VPS or load balancer.

Tuning without metrics?

Avoid guessing—use access log QPS, CPU, and upstream latency first.

Replace Nginx with CDN?

CDN caches static; origin Nginx still common for dynamic API proxy.

Config in Git?

Store sanitized templates; inject secrets on deploy. Cert paths differ per server.

When to restart vs reload?

reload for config; restart after package upgrade or if workers stuck.