[ OK ]Initializing kernel...
~/im/blog
Hire Me

Let's Talk

Got an infrastructure problem or need an extra hand? I'm open to discussing new projects.

Get in touch

Connect

Find me on social media and professional networks.

© 2026 Irfan Miral. All rights reserved.Developed byIrfan Miral
Privacy PolicyTerms & Conditions
HomeServicesAbout/ResumeBlogContactTools
2026-05-14• 5 min read

HAProxy or Nginx as a Reverse Proxy: How I Choose

DevOps HAProxy Nginx Load Balancing

Advertisement

Nginx and HAProxy get compared constantly. The honest answer is that there is a massive amount of overlap. Both can terminate TLS, load balance across multiple backends, and route traffic based on hostnames or paths. For a huge number of setups, either one works perfectly fine.

But they were built with very different primary jobs in mind. That difference becomes painfully obvious once your setup evolves past "one app server sitting behind a proxy."

Nginx: The default for a single app server

If you have exactly one application server, maybe paired with a couple of static asset directories, and the proxy's job is just TLS termination plus routing requests, Nginx is the simpler choice. It does this job extremely well:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location /static/ {
        root /var/www/example.com;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

This configuration handles three jobs at once: serving static files directly, terminating TLS, and proxying everything else to the application. For a single backend, that is exactly the right amount of complexity. Additionally, almost every developer has seen Nginx syntax before, which matters a lot when you aren't the only person maintaining it.

HAProxy: The default once there's more than one backend

The moment you spin up a second instance of your application, the questions fundamentally change. Which backends are currently healthy? How should load be distributed? What happens to a request mid-flight if a backend suddenly dies?

This is HAProxy's core job, and it shows in how directly the configuration expresses it:

frontend web
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
    default_backend app_servers

backend app_servers
    balance roundrobin
    option httpchk GET /healthz
    server app1 10.0.0.11:3000 check
    server app2 10.0.0.12:3000 check
    server app3 10.0.0.13:3000 check

option httpchk GET /healthz means HAProxy actively polls each backend's health endpoint. If a backend starts failing those checks, HAProxy automatically pulls it out of rotation. Zero manual intervention required.

HAProxy's built-in stats page gives you a live, detailed view of exactly which backends are up, how many connections each one is handling, and the response times per backend. That observability is genuinely indispensable once you have more than one server to keep track of.

Using both together

These tools are not mutually exclusive. A very common architecture for scaling beyond a single server is placing HAProxy at the edge. HAProxy handles the TLS termination and load balancing across multiple application servers. Then, each application server runs Nginx locally to serve static files and proxy requests directly to the application process.

HAProxy doesn't need to know anything about static files. Nginx doesn't need to know anything about the overall server cluster. Each piece strictly does the job it is best at.

The actual decision

If you have one backend and your main goal is TLS termination plus basic routing, Nginx is simpler, more familiar, and entirely sufficient. Sticking HAProxy in front of a single backend adds an entire network layer without adding much capability.

But if you have more than one backend instance and health-aware load balancing actually matters (even if it's just two app servers for redundancy), HAProxy is built exactly for that. Trying to replicate HAProxy's robust health check model in Nginx means bolting on third-party modules or writing far more complex configurations than HAProxy needs for the exact same result.

The question isn't which tool is objectively better. The question is whether "which backend should this request go to, and is that backend even healthy?" is a problem your infrastructure needs answered. Once it is, HAProxy easily earns its place.

Advertisement

Need help with this?

If you'd rather have someone handle Web Server Configuration for you, that's exactly what I do.

Get in Touch
PreviousSetting Up a Mail Server That Doesn't End Up in SpamNext Docker vs LXC on Proxmox: What I Actually Run in Production