Skip to content

Chapter 4 of 8

Reverse Proxying, Upstreams, and Backend Protocols

An upstream {} block defines a named group of backend servers that nginx will load-balance across. A typical example declares several server entries, optional weights, and a keepalive pool: upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; keepalive 32; }. You then point a location at it with proxy_pass http://backend;. By default nginx uses round-robin; it also supports least_conn, ip_hash, and random out of the box. ip_hash hashes the client's IP to pick a backend, which keeps the same client on the same server — handy for stateful apps — but it cannot distinguish clients behind a shared NAT or proxy, and adding or removing a backend remaps most clients. For finer control, the server entries accept parameters such as weight=N to bias the share, max_fails and fail_timeout to mark a server down after consecutive errors, backup to use the server only when primaries are unavailable, and down to remove it from rotation during maintenance without deleting the line.

The proxy_pass directive has a subtle but critical behaviour tied to whether it ends with a slash. Without a trailing slash, the full original URI is forwarded to the upstream including the matched location prefix — so location /api/ { proxy_pass http://backend; } forwards /api/users as /api/users. With a trailing slash, the matched location prefix is replaced with /, and the same request becomes /users. Matching the trailing slash on the location to the slash on the upstream is therefore the usual recipe for clean URL translation. Beyond the URL, several headers must be set explicitly so the upstream sees the original client. proxy_set_header Host $host; preserves the virtual-host name; proxy_set_header X-Real-IP $remote_addr; and proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; forward the real client IP; and proxy_set_header X-Forwarded-Proto $scheme; tells the upstream whether the original request was HTTP or HTTPS.

Nginx speaks several backend protocols. proxy_pass handles plain HTTP and HTTPS upstreams. fastcgi_pass speaks the FastCGI protocol used by PHP-FPM and similar applications, and requires fastcgi_param mappings instead of proxy_set_header — the canonical PHP-FPM snippet binds fastcgi_pass to a Unix socket and supplies SCRIPT_FILENAME \(document_root\)fastcgi_script_name;. uwsgi_pass connects to a uWSGI application server, which is the standard way to serve Python WSGI apps. For microservices, grpc_pass routes gRPC traffic to a backend and requires HTTP/2 (TLS or cleartext h2c), which became stable in nginx 1.13.10. Regardless of protocol, several tunables control the connection: proxy_connect_timeout caps how long nginx waits to establish a TCP connection (default 60s), proxy_send_timeout caps how long it takes to send the request, and proxy_read_timeout caps the gap between successive reads from the upstream (default 60s) — the last of these is the one to bump for long-polling, Server-Sent Events, and WebSockets.

For body sizes, client_max_body_size defaults to 1m; raise it (for example to 50m) to allow large file uploads, otherwise nginx returns 413 Request Entity Too Large. client_body_buffer_size sets the in-memory buffer (default 8k), and anything larger spills to client_body_temp_path. Finally, proxy_buffering on; (the default) buffers the entire upstream response before forwarding to the client, which protects upstream from slow clients and enables proxy_cache. Setting it to off streams responses straight through with minimal buffering, which is the right choice for large media, Server-Sent Events, and WebSockets — combine it with add_header X-Accel-Buffering no; when the response is gated by an upstream you control.

All chapters
  1. 1Nginx Fundamentals and Process Model
  2. 2Core Configuration Directives and Performance Knobs
  3. 3HTTP Routing: Servers, Locations, and Rewrites
  4. 4Reverse Proxying, Upstreams, and Backend Protocols
  5. 5Caching and Compression
  6. 6TLS, SSL, and Connection Hardening
  7. 7Access Control, Rate Limiting, and Logging
  8. 8Advanced Routing, Variables, and Security Headers

Drill it

Reading is not remembering. These come from the Nginx Configuration Essentials deck:

Q

What does nginx stand for?

engine x — a high-performance open-source HTTP server, reverse proxy, and IMAP/POP3 mail proxy originally written by Igor Sysoev and first released in 2004...

Q

What is nginx's primary process model?

A single master process that reads configuration, manages sockets, and spawns worker processes (default count = CPU cores). Workers handle all incoming connecti...

Q

How do you reload nginx configuration without dropping connections?

Send SIGHUP to the master process (or run nginx -s reload). The master re-reads config, spawns new workers with the new config, and gracefully shuts down old wo...

Q

What is the difference between <code>nginx -s stop</code> and <code>nginx -s quit</code>?

stop sends SIGTERM to workers and forces them to exit immediately, closing open connections. quit sends SIGQUIT, which lets workers finish serving current reque...