Nginx
Nginx (pronounced "engine-x") is a high-performance web server, reverse proxy, and load balancer. Its event-driven architecture handles tens of thousands of concurrent connections in a few megabytes of memory, which made it the standard front door for web applications: it terminates TLS, serves static files, and forwards dynamic requests to your app servers.
Even in a world of cloud load balancers and Kubernetes ingress controllers, Nginx knowledge pays off constantly — the ingress controller most clusters run is Nginx, and nearly every VPS deployment puts it in front of Node, Python, or PHP processes.
TL;DR
- Nginx's main production role is reverse proxy: it receives all traffic, terminates TLS, serves static files directly, and proxies the rest to app servers.
- Configuration is a hierarchy:
http→server(one per site/domain) →location(one per URL pattern). - Location matching has precedence rules — exact
=beats prefix beats regex; longest prefix wins. - Always test before reload:
nginx -t && nginx -s reload(reload is zero-downtime). proxy_passneeds the standard header set (Host,X-Forwarded-For,X-Forwarded-Proto) or your app sees wrong client IPs and protocols.- Built-in load balancing (round-robin, least_conn, ip_hash) covers most multi-backend needs.
Quick Example
A production-shaped reverse proxy: TLS, static assets served directly, everything else to a Node app:
Core Concepts
The Configuration Hierarchy
Nginx picks the server block by matching listen port + server_name against the request's Host header, then picks a location inside it.
Location Matching Rules
The part of Nginx that bites everyone. Precedence:
When behavior seems wrong, it's almost always a regex location stealing a request you thought a prefix owned.
Reverse Proxying
The proxy_set_header lines are not optional decoration:
For WebSockets, add the upgrade handshake:
Load Balancing
Failed backends are taken out of rotation passively (max_fails). For deeper strategies and health-check trade-offs see Load Balancing.
Common Production Patterns
Rate Limiting at the Edge
Stop brute force before it reaches the app:
Response Caching
Nginx can cache upstream responses, absorbing read traffic:
proxy_cache_use_stale is a cheap resilience win — see Caching Layers.
Gzip/Brotli and Security Headers
See Security Headers for the full set.
SPA Fallback
Single-page apps need unknown paths routed to index.html:
Best Practices
nginx -tbefore every reload. A syntax error in a reload is caught; in a restart it takes the site down.- One
serverblock per site, stored in/etc/nginx/sites-available/(orconf.d/), enabled by symlink — keepnginx.confitself boring. - Set real timeouts. Defaults (
proxy_read_timeout 60s) silently kill slow endpoints and idle WebSockets; size them to your traffic. - Log in a structured format and ship access/error logs to your log aggregation system;
$upstream_response_timein the log format is free latency telemetry. - Automate certificates with certbot/acme.sh — expired certs remain a top self-inflicted outage.
Common Mistakes
Trailing-Slash Surprises in proxy_pass
A single character changes whether the path prefix is stripped. Decide intentionally.
if Inside location
Nginx's if is famously treacherous ("if is evil" in the official wiki) — it interacts badly with other directives. Prefer map, try_files, or separate locations.
Forgetting the Real-IP Chain
If Nginx sits behind a CDN or cloud load balancer, $remote_addr is the CDN's IP. Use the real_ip module with the upstream's trusted ranges, or your logs, rate limits, and geo rules all target the wrong address.
Restart Instead of Reload
systemctl restart nginx drops connections; reload starts new workers and drains old ones with zero downtime. Restart is almost never what you want in production.
FAQ
Nginx or Apache?
Nginx's event-driven model handles high concurrency with less memory, and its config style suits the reverse-proxy role that dominates modern deployments. Apache remains fine (and .htaccess is convenient on shared hosting), but new deployments overwhelmingly choose Nginx.
Do I still need Nginx behind a cloud load balancer or CDN?
Often yes, in a reduced role: local static serving, request buffering for slow clients, per-node rate limits, and app-specific routing. In containerized setups the same jobs move to the ingress controller — which is usually Nginx anyway.
What's the difference between Nginx and an ingress controller?
The Kubernetes ingress-nginx controller is Nginx plus an operator that writes its config from Ingress resources. Same engine, declaratively managed — debugging it still requires understanding Nginx semantics.
What about Caddy and Traefik?
Caddy gives automatic HTTPS with radically simpler config — excellent for small deployments. Traefik discovers backends from Docker/Kubernetes labels — strong in dynamic container environments. Nginx remains the most battle-tested and widely documented of the three.
Can Nginx serve as an API gateway?
Yes — rate limiting, auth subrequests (auth_request), routing, and caching cover many gateway needs; Kong is literally built on it. Purpose-built gateways add key management, quotas, and dashboards on top. See API Security.
Related Topics
- Load Balancing — Algorithms and health-check strategy
- HTTPS & TLS — What TLS termination involves
- Caching Layers — Where proxy caching fits
- CDN — The layer in front of Nginx
- WebSockets — Proxying long-lived connections
- Security Headers — Hardening responses at the edge
- Kubernetes — Ingress controllers built on Nginx