nginx · Distributed Systems

Sadeen Faqih & Mohammadkhair Awwad. This is the slide deck. On a phone, the interactive part is the live page.

nginx

One front door for a distributed system.

Sadeen Faqih
Mohammadkhair Awwad

It answers every caller and connects each one to a healthy backend. Theory, step-by-step simulations, then a live server you can hit from your phone.

Today's exchange

  1. 1Why nginx existsone server is not enough, the C10K problemSadeen
  2. 2Inside nginxmaster and workers, the event loopSadeen
  3. 3The reverse proxyone request, step by step, and the config behind itSadeen
  4. 4Balancing the loadfive methods, consistent hashing, failoverMohammadkhair
  5. 5Shielding the backendscaching and rate limitingMohammadkhair
  6. 6nginx in a distributed systemsingle point of failure and high availabilityMohammadkhair
  7. 7Live on bzu.awwad.siwe deploy it now, then you send the trafficMohammadkhair
  8. 8Trade-offs and questionswhere nginx fits, and where it doesn'tBoth

One server is not enough

What nginx is

A web server, reverse proxy, cache and load balancer in one small event-driven C program.

Six jobs, one process

  • web serverserves this deck's files
  • reverse proxypages 7–8
  • load balancerpages 10–12
  • cachepage 13
  • rate limiterpage 14
  • TLS terminatorlive, page 16
  1. 2002Igor Sysoev starts nginx to handle the traffic of Rambler, a large Russian portal, as a solution to C10K.
  2. 2004First public release, 4 October 2004.
  3. 2011Nginx, Inc. founded to offer commercial support and NGINX Plus.
  4. 2019F5 acquires Nginx, Inc. for US$670 million.
  5. 2024Core developer Maxim Dounin forks it as freenginx.
  6. today30.0% of websites whose web server is known run nginx, second only to Cloudflare's server at 33.7% (W3Techs, 11 Nov 2026).

Master and workers

A few long-lived processes, not one thread per visitor.

Threads vs. the event loop

The reverse proxy

Clients only ever talk to nginx. Backends only ever talk to nginx.

The phone sends

GET /api/hello HTTP/1.1
Host: bzu.awwad.si
User-Agent: Mozilla/5.0 (iPhone…)
nginx
terminates TLS
adds headers

backend-2 receives

GET /api/hello HTTP/1.1
Host: bzu.awwad.si
X-Real-IP: 203.0.113.7
X-Forwarded-For: 203.0.113.7
X-Forwarded-Proto: https
X-Request-Id: 7b75769283e2…
  • 1Hides the topology. Our backends listen on 127.0.0.1 only. The internet can't reach them, only nginx can.
  • 2One certificate. TLS ends at nginx; backends speak plain HTTP on localhost.
  • 3One place for policy: logs, limits, caching, compression, for every backend at once.
  • 4Backends come and go and clients never notice: same name, same IP.

A request's journey

Reading an nginx config

Blocks inside blocks; settings flow inward unless a block overrides them.

main · nginx.confuser www-data; worker_processes auto;
eventsworker_connections 768;
httpinclude /etc/nginx/sites-enabled/*; ← our file lands here
upstream bzu_rrserver 127.0.0.1:9101;
server 127.0.0.1:9102;
server 127.0.0.1:9103;
server · bzu.awwad.silisten 80; root /var/www/bzu.awwad.si;
location /api/proxy_pass http://bzu_rr;
location = /api/cachedproxy_cache bzu_cache;
  • One file per site. Ours is self-contained; delete its symlink and nginx is back to how it was.
  • Shared names. Everything at http level (upstreams, zones, caches) is global to the server, so ours all start with bzu_.
  • Always: nginx -t before reload.

Five ways to pick a backend

Consistent hashing

Sticky routing that survives a backend leaving.

When a backend dies

Passive health checks: real requests are the probes. (Active checks are NGINX Plus only.)

Caching at the edge

Answer repeated questions without asking the backend.

Rate limiting: the leaky bucket

nginx itself can fail

The front door is one point of failure, so real systems run more than one.

  • Floating IP. keepalived (VRRP) moves one IP between two nginx boxes.
  • DNS round robin. Several A records, one per nginx. Simple, but DNS caches slow down failover.
  • Anycast. The same IP announced from many places; how large CDNs spread their edge.
  • Kubernetes. nginx-based ingress controllers run several replicas. The community ingress-nginx project was retired in March 2026; Gateway API is the recommended path.

Live: deploy in eight commands

On a real VPS that already serves 8 other sites. Nothing else may break.

  1. 1
    DNS record (added at the start of the talk)A bzu → 57.129.172.197
  2. 2
    Start three backends on 127.0.0.1:9101–9103sudo docker compose up -d
  3. 3
    Publish this deck as static filessudo cp -r site/. /var/www/bzu.awwad.si/
  4. 4
    Install the sitesudo cp nginx/bzu.awwad.si.conf /etc/nginx/sites-available/bzu.awwad.si sudo ln -s /etc/nginx/sites-available/bzu.awwad.si /etc/nginx/sites-enabled/
  5. 5
    Test, then reload gracefullysudo nginx -t && sudo systemctl reload nginx
  6. 6
    Try it before DNS is readycurl -H "Host: bzu.awwad.si" http://127.0.0.1/api/hello
  7. 7
    HTTPS: nginx terminates TLSsudo certbot --nginx -d bzu.awwad.si --redirect
  8. 8
    Watch nginx decidesudo tail -f /var/log/nginx/bzu.access.log

Your turn: join the exchange

QR code for https://bzu.awwad.si/live/

bzu.awwad.si/live

Open it on your phone and press Send a request. You'll see which backend answered, and every header nginx added.

Live experiments

  1. 1
    Everyone: “Send 10” with round robin.The three bars grow together.
  2. 2
    Switch to ip_hash.Prediction: if we all share one campus IP (NAT), we all land on one backend.
  3. 3
    Switch to “sticky” (hash by phone).You keep your backend; your neighbour may have a different one.
  4. 4
    We kill a backend while you keep sending.sudo docker stop bzu-backend-2Its bar says DOWN; your phone still gets answers.
  5. 5
    Press “Spam 10” and “Cached”.429 after the burst; HIT with the same timestamp for 10 s.

Where nginx fits, and where it doesn't

Built forNotable
nginxweb server + reverse proxy + cache in oneevent loop, static config + graceful reload; active health checks and a live API are in the paid NGINX Plus
HAProxydedicated TCP/HTTP load balanceractive health checks and a detailed stats page in the open-source version
Envoyservice meshes and microservicesconfigured live over an API (xDS); the data plane of Istio
Caddysimple sites with automatic HTTPSgets and renews certificates by default; written in Go
Apache httpdgeneral web server with modulesprefork / worker / event models, per-directory .htaccess

Takeaways

  1. 1An event loop per core handles thousands of connections without a thread each.
  2. 2As a reverse proxy, nginx is the one front door: TLS, routing, headers, logs.
  3. 3It spreads load, routes around dead backends, caches and rate-limits, all from one config file.
  4. 4It is itself a single point of failure: run two, with a floating IP or DNS.

Questions?

Sources

  • nginx.org/en/docs: ngx_http_upstream_module, ngx_http_limit_req_module, ngx_http_proxy_module
  • W3Techs web server usage, 11 Nov 2026 · w3techs.com/technologies/overview/web_server
  • D. Kegel, “The C10K problem”, 1999 · kegel.com/c10k.html
  • Kubernetes blog, “Ingress NGINX Retirement”, 11 Nov 2025
  • Demo code and runbook: this site, bzu.awwad.si

nginx