guest@6admin.io:~$

Haproxy: the reverse proxy that took over from Pound

The blog covered Pound in 2008 : a very light reverse proxy that terminates TLS and balances to a pool. Pound does that job with minimal elegance, but as soon as you need to route on content (a Host to a cluster, a URL to a specific backend, a sticky session), one step up: haproxy 1.3, by Willy Tarreau, stabilizing toward 1.4.

The block that says it all

frontend web
    bind *:80
    mode http
    acl is_app    hdr(host) -i app.domain.tld
    acl is_static path_beg /static/
    use_backend app      if is_app
    use_backend statics  if is_static
    default_backend app

backend app
    mode http
    balance roundrobin
    option httpchk HEAD /health
    server web1 192.168.10.11:8080 check inter 5s fall 2 rise 2
    server web2 192.168.10.12:8080 check inter 5s fall 2 rise 2

backend statics
    mode http
    balance source
    server s1 192.168.10.21:80

tcp mode and http mode: in TCP, haproxy is a brute balancer (TLS pass-through, any protocol); in HTTP, it parses the request and routes on its content. The ACLs do the rest: hdr(host), path_beg and an operator grammar that keeps the config readable, which Pound did not offer.

What it does that Pound does not

  • Per-backend health checks (option httpchk): a dead server leaves the pool after two probes, not at the first client timeout;
  • Sticky sessions (balance source or cookies in http mode), which Pound’s blind roundrobin made painful with non-stateless apps;
  • The stats page (stats enable): a backend taking 40% of traffic becomes visible immediately;
  • L7 granularity: routing on URL, Host, a cookie, a User-Agent: in 2009 that is what separates a proxy from a balancer.

Era reflexes

  • balance roundrobin as the default, leastconn for inhomogeneous backends;
  • the keepalived/VRRP pair for haproxy’s own redundancy (the SPOF moves, it does not vanish);
  • timeouts set explicitly (timeout connect 5s, timeout server 30s), haproxy’s generous defaults being made for long connections;
  • and the config tested with haproxy -c before every deploy: the command that saved more evenings than every backup in the house, because a typo in a frontend cuts the whole site and you always discover it during dinner.

[edit: 2026] Longevity, the only real surprise

Pound ended up forgotten; haproxy crossed everything: the same config grammar still runs in production today (HAProxy 3.x), with the same frontends/backends/ACLs, agglomerated with fifteen years of features (HTTP/2, gRPC, TLS 1.3, maps, DNS discovery). That is the rarity in network tooling: a tool whose 2009 config still loads as-is in the current version. The era’s reverse proxy became the default edge and the readable config had everything to do with it.

[edit: 2026] The Ansible implementation of all this: the haproxy role .