How do you configure NGINX as a reverse proxy with load balancing, health checks, and SSL termination for a microservices architecture?
Quick Answer
Define upstream blocks with backend servers and load balancing algorithm, configure proxy_pass with appropriate headers, add SSL certificate and key, and use passive health checks to remove failed backends.
Detailed Answer
Architecture
Clients → NGINX (SSL termination, load balancing) → Backend services (HTTP)
Load Balancing Algorithms
- round-robin (default): Even distribution - least_conn: Sends to server with fewest active connections - ip_hash: Sticky sessions based on client IP - random two least_conn: Picks 2 random servers, sends to one with fewer connections (good for large clusters)
SSL Termination
NGINX handles TLS handshake and decryption. Backend communication is plain HTTP (faster, simpler cert management). For security-sensitive environments, use mTLS to backends.
Health Checks
- Open source: Passive only — marks server as failed after N consecutive errors - NGINX Plus: Active health checks — probes backends periodically - Use max_fails and fail_timeout to tune failure detection
Essential Proxy Headers
- X-Real-IP: Client's actual IP (not NGINX's) - X-Forwarded-For: Full proxy chain - X-Forwarded-Proto: Original protocol (https) - Host: Preserve original Host header for virtual hosting
Code Example
upstream api_backend {
least_conn;
server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.13:8080 backup; # Only used when others fail
keepalive 32; # Connection pooling to backends
}
server {
listen 443 ssl http2;
server_name api.example.com;
# SSL configuration
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options nosniff;
location /api/ {
proxy_pass http://api_backend;
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;
# Timeouts
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 10s;
# Connection reuse
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}Interview Tip
Include keepalive connections to backends (proxy_http_version 1.1 + Connection header) — this is a major performance optimization most candidates miss. Also mention the backup server for resilience.