Nginx

On this page 7

Nginx (pronounced “engine-x”) is an open-source web server, reverse proxy and load balancer built on an event-driven, asynchronous architecture that lets a small, fixed number of processes handle many thousands of concurrent connections. Among web servers, it is the usual choice for serving static files, terminating TLS and passing dynamic requests to application back ends such as PHP-FPM, Node.js or Python application servers.

Nginx was first released publicly in 2004 to address the C10k problem, the difficulty of serving ten thousand simultaneous clients on one machine. It is distributed under a two-clause BSD license, and a commercial edition, NGINX Plus, adds features such as active health checks and a live monitoring API.

How the Nginx event-driven architecture works

Nginx runs as one master process and several worker processes. The master process runs with elevated privileges, reads the configuration, binds to ports such as 80 and 443 and manages the workers; the workers handle all client traffic under an unprivileged account.

Each worker runs a non-blocking event loop on top of the operating system’s notification mechanism, such as epoll on Linux or kqueue on BSD and macOS. Instead of dedicating a thread to each connection and waiting while it is idle, a worker reacts only when a socket is ready to read or write. As a result, memory use grows slowly with connection count, because an idle keep-alive connection costs only a few kilobytes of state rather than a whole thread or process.

The practical ceiling on concurrent connections is roughly worker_processes multiplied by worker_connections, limited further by the file descriptor limit. When Nginx works as a reverse proxy, each client normally consumes two connections, one to the client and one to the upstream server, so the effective client capacity is about half.

The table below lists the core directives that shape this model and their usual values.

DirectiveTypical valueWhat it controls
worker_processesauto (one per CPU core)Number of worker processes
worker_connections512 compiled default, often 1024 or moreConnections each worker may hold open
worker_rlimit_nofileAt least twice worker_connectionsFile descriptor limit per worker
keepalive_timeout75 s default, often 15-65 sHow long idle client connections stay open
client_max_body_size1 MB defaultLargest accepted request body, such as uploads
sendfileon for static contentKernel-level file transfer without copying to user space
Core performance directives in Nginx

Configuration structure and request matching

Nginx is configured through plain-text files with nested contexts, usually rooted at /etc/nginx/nginx.conf. The http context holds global web settings, each server block defines a virtual host selected by listen and server_name, and each location block defines how a group of URIs is handled.

Location selection follows a fixed precedence order rather than the order in the file, which is one of the most common sources of configuration errors. The table summarizes the rules Nginx applies when it chooses a location for a request URI.

ModifierMatch typePrecedence
=Exact matchHighest; search stops immediately
^~Prefix match that skips regex checksWins if it is the longest prefix
~ and ~*Regular expression, case-sensitive or notFirst matching regex in file order
NoneOrdinary prefix matchLongest prefix, used if no regex matches
Location modifiers and their precedence

Changes take effect through a graceful reload: nginx -t validates the syntax, and nginx -s reload makes the master start new workers with the new configuration while old workers finish their open requests. Unlike Apache, Nginx has no per-directory .htaccess files, which removes a filesystem lookup on every request but means all rules live in the central configuration.

Nginx compared with other web servers

Nginx differs from its neighbors mainly in concurrency model, configuration style and dynamic content handling. The comparison below covers the servers most often evaluated alongside it.

ServerConcurrency modelDynamic contentDistinctive trait
NginxEvent-driven workersProxied to PHP-FPM or app serversLow memory, strong reverse proxy
ApachePrefork, worker or event MPMEmbedded modules or PHP-FPM.htaccess and broad module set
CaddyGo runtime with goroutinesReverse proxy or FastCGIAutomatic HTTPS by default
OpenLiteSpeedEvent-drivenLSAPI for PHP.htaccess rewrite compatibility
Nginx and related web servers

Nginx does not execute PHP itself. It forwards PHP requests over the FastCGI protocol with fastcgi_pass to a PHP-FPM pool, usually through a Unix socket, and serves images, CSS and JavaScript directly from disk. This separation of static and dynamic work is the reason a common stack places Nginx in front of every application tier.

Typical roles in a server stack

The same Nginx binary can fill several distinct roles, and many deployments combine them in one configuration. Choosing the role determines which modules and directives matter most.

RoleKey directivesTypical benefit
Static file serverroot, try_files, expiresFast delivery with low CPU use
Reverse proxyproxy_pass, proxy_set_headerShields and offloads application servers
Load balancerupstream, least_conn, ip_hashSpreads traffic across back ends
TLS terminationssl_certificate, ssl_protocolsCentral certificate and cipher management
Cache layerproxy_cache, fastcgi_cacheServes repeated responses without the back end
Common Nginx roles

Open-source Nginx balances load with round robin by default and also supports least connections, IP hash, generic hash and random selection. Its health checking is passive: a back end is marked unavailable after max_fails failed attempts, one by default, within fail_timeout, 10 seconds by default. Active probing of back ends requires NGINX Plus or a third-party module.

Limitations and common mistakes

Nginx is efficient, but its defaults and matching rules cause predictable misconfigurations. Most problems in production trace back to a short list of errors.

  • Missing proxy headers: without Host, X-Forwarded-For and X-Forwarded-Proto, applications log the proxy address and generate wrong redirect URLs.
  • Unsafe PHP handling: passing any URI ending in .php to PHP-FPM without checking that the file exists can let uploaded files be executed as scripts.
  • Low upload limits: the 1 MB client_max_body_size default produces HTTP 413 errors on media uploads.
  • Misread location order: placing a regex location expecting file order to win over a longer prefix match.
  • Blocking modules: third-party code that performs blocking I/O inside a worker stalls every connection that worker serves.

Dynamic modules have been supported since version 1.9.11, yet many modules must still be compiled against the exact Nginx version in use. That makes upgrades slower than with servers that load plugins at run time.

In plain words

Nginx is the receptionist at the front door of a website. It greets every visitor, hands out ready-made items such as pictures and style files immediately, and passes only the requests that need real work to the specialists behind it.

Its strength is that one receptionist can juggle thousands of visitors at once, because it never stands idle waiting for one person to finish. That is why so many busy sites put Nginx first in line.

A real-world example

A small agency runs an online store on a virtual server with 4 CPU cores and 8 GB of RAM. Before a seasonal sale, pages slow down because the old setup serves every image through the PHP application.

The administrator places Nginx in front with worker_processes auto, 4,096 worker connections, a try_files rule that serves product images directly from disk and fastcgi_cache for anonymous visitors with a 60-second validity. PHP-FPM now receives only cart, checkout and logged-in requests, and client_max_body_size is raised to 20 MB for product photo uploads.

During the sale, the store handles about five times more visitors with lower CPU use on the PHP tier, and response times for cached catalog pages stay below 50 milliseconds.