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

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

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

References