All posts

HAProxy vs nginx for Load Balancing: An Honest, Use-Case-Driven Comparison

HAProxy grew from a load balancer; nginx grew from a web server. That origin gap decides most of the choice — and active health checks, free in HAProxy but paid in nginx, are where it gets real.

The short version

HAProxy is a load balancer that grew a few extra skills. nginx is a web server that learned to balance. That origin gap still decides most of the choice in 2026. Need a dedicated TCP/HTTP front door with deep health checking and connection queuing? Reach for HAProxy. Already terminating TLS, serving static assets, and caching, and you want the same process to fan HTTP across a backend pool? nginx earns its keep. Both are fast enough that raw throughput is almost never what decides it.

This is not a benchmark war

You will find posts claiming HAProxy beats nginx by some single-digit percentage on requests per second, and posts claiming the reverse. Both are usually true and both are usually beside the point. On modern hardware either tool will saturate a 10 GbE link, or push six-figure requests per second, long before it becomes the bottleneck in a real system. Your database, your TLS handshake rate, or your application latency falls over first.

The honest question is not "which is faster." It is "which model fits the job" — where in the stack you are balancing, and how badly you need to know your backends are actually alive.

Layer 4 vs Layer 7, plainly

A Layer 4 load balancer works at the TCP/UDP level. It sees source and destination IPs and ports, picks a backend, and shovels bytes. It never parses what is inside the connection. That makes it fast and protocol-agnostic — a good fit for things that are not HTTP: a Postgres replica pool, a Redis cluster, an SMTP relay, a gRPC stream you would rather not terminate.

A Layer 7 load balancer terminates the connection, parses the application protocol, and routes on content — path, host header, cookie, method. That is what you want when /api goes to one pool and /static goes to another, when you need sticky sessions keyed on a cookie, or when you are rewriting headers in flight.

Both tools do both layers. HAProxy has native TCP (Layer 4) and HTTP (Layer 7) modes from a single config. nginx does HTTP in its core http {} block and TCP/UDP through the stream {} module, which has to be compiled in with --with-stream. Most distro packages include it, but check before you assume.

Health checks: the real dividing line

Here the comparison stops being academic. Active health checks in open-source nginx are not free.

Open-source nginx does passive health checks. It marks a backend down only after live traffic to it fails, governed by max_fails and fail_timeout. Real user requests get thrown at a dead server before nginx notices. Proactive probing — nginx reaching out to each backend on its own schedule and pulling it from rotation before a user ever lands on it — requires NGINX Plus, the commercial tier from F5, whose list pricing starts around $2,500 per instance per year for basic support and climbs from there. (F5 bought NGINX for $670M in 2019. In 2024 a core maintainer forked the open-source project as freenginx after a dispute over how the company handled security releases — which tells you something about where the open and commercial roads diverge.)

HAProxy ships active health checks in the free, open-source build. It probes backends on an interval, sends a real HTTP/1.1 request or a bare TCP connect, matches the expected response, and applies rising and falling thresholds before declaring a server up or down. It supports agent checks, where a small process on the backend reports its own weight or readiness, and it queues connections when every server is busy instead of failing them outright. For a high-availability database cluster or a payment path, that gap is the whole game.

Architecture and operations

Both run an event-driven, non-blocking core, and both are multi-threaded. HAProxy has been multi-threaded since 1.8 (the current line is 3.x), with a scheduler per thread under a master/worker model. nginx uses a master process that spawns workers, one per core by convention. Neither is starved for CPU scalability.

Where they feel different is the surrounding job. nginx is one binary that terminates TLS, serves files, caches responses, and reverse-proxies; if your edge already does all of that, adding upstream balancing is a few lines, not a new component — and it is the default ingress for a large share of Kubernetes clusters. HAProxy is built around balancing. It offers more algorithms out of the box (roundrobin, leastconn, source, uri, consistent hashing), plus a runtime admin socket and a detailed stats page for watching backends live. It does not serve static files. That is simply not its job.

Observability tilts toward HAProxy for pure balancing work: its stats endpoint and Prometheus exporter expose per-backend queue depth, session rates, and check status with no paid tier in the way. nginx's richest live metrics again sit behind NGINX Plus.

How to actually decide

Pick nginx when the box is already a web server — TLS termination, static content, response caching — and balancing is one more hat it wears. Pick it for Kubernetes ingress, where the ecosystem expects it. Accept that without Plus, your health checking is reactive, not proactive.

Pick HAProxy when balancing is the primary job and correctness under failure is the thing you cannot get wrong: database replica pools, raw TCP services, microservice gateways with content-based routing, anywhere you want active health checks and connection queuing without writing a cheque to F5. Put a web server or cache behind it if you need one.

Plenty of serious stacks run both. nginx or a CDN sits at the very edge for TLS and caching; HAProxy sits underneath, fanning traffic across application and data tiers. That is not indecision. It is using each tool for the thing it was built to do.

How we think about it at Beebeeb

We build end-to-end encrypted, zero-knowledge storage on dedicated servers in Falkenstein, Germany, and high availability stops being optional the moment you hold people's encrypted files. For us the load-balancer question is not about peak requests per second. It is about knowing, proactively, that a backend is healthy before a request lands on it — exactly the active-health-check problem above. The encryption that protects your data happens on your device no matter which node answers, so the job at the edge is narrow and unforgiving: correct routing and clean failover, on every tier including the free one.

If you want to see what that posture looks like from the user's side, our feature overview covers the client capabilities and the security page walks through the model end to end.

There is no "winner" between HAProxy and nginx. There is only the one whose default behavior matches the failure you are most afraid of.

Files only you can read

Beebeeb is end-to-end encrypted, zero-knowledge cloud storage — stored in Falkenstein, Germany, open source, with a 14-day free trial on every plan. Encryption happens on your device; we only ever hold ciphertext we can’t read.

Join the waitlist See pricing How the encryption works