Distribute traffic, remove unhealthy servers automatically
A single application server does not scale indefinitely and goes offline instantly on failure. HAProxy distributes requests across multiple backend servers, automatically detects failed instances through health checks, and turns several individual servers into a resilient, horizontally scalable unit.
Table of Contents
- 1. Why a load balancer like HAProxy is needed
- 2. Architecture: frontend, backend and ACLs
- 3. Installation and a first haproxy.cfg
- 4. Balancing algorithms compared
- 5. Health checks and automatic server removal
- 6. Sticky sessions for stateful applications
- 7. SSL termination and layer 7 routing
- 8. Stats dashboard and monitoring
- 9. HAProxy compared to nginx and cloud load balancers
- 10. Summary
- 11. FAQ
1. Why a load balancer like HAProxy is needed
HAProxy is one of the most widely used software load balancers in the Linux world and solves two problems at once: scaling and failure resistance. A single application server has a fixed upper limit on concurrent connections and CPU capacity, no matter how well the application itself is optimized. Once that limit is reached, the only real fix is distributing traffic across multiple servers instead of continually sizing up a single one.
At the same time, a single application server is also a single point of failure. If it goes down, the service is completely offline, even if the application itself runs flawlessly. This is exactly where HAProxy comes in: it distributes incoming requests across a group of backend servers using configurable algorithms and automatically removes any server from rotation that stops responding to a health check. Clients notice nothing, they still address only a single endpoint.
In typical PHP and Magento setups, HAProxy sits in front of multiple identically configured application servers that all access the same session storage and the same database. This enables horizontal scaling: when load increases, another application server is added and registered in the HAProxy configuration, with no downtime or application change required. The following sections walk through the entire path from installation to a production ready setup with SSL and monitoring.
2. Architecture: frontend, backend and ACLs
The HAProxy configuration file, located by default at /etc/haproxy/haproxy.cfg, is divided into clearly separated blocks. A frontend block defines on which port and protocol HAProxy accepts requests, while a backend block contains the list of actual target servers requests get forwarded to. This strict separation allows a single frontend to be coupled to several different backends, depending on rules such as URL path or host header.
Access Control Lists, or ACLs, are the tool used to make these routing decisions. An ACL checks a condition, for example whether the path starts with /api/, and routes into a specific backend based on the result. This lets a single HAProxy instance distribute both static content and dynamic PHP traffic to different backend groups, without needing two separate load balancers.
Another important building block is the defaults block, where shared timeout values, logging options and mode (http or tcp) are centrally set for all subsequent frontend and backend blocks. This structure keeps HAProxy configurations manageable even with many backends, because recurring settings do not need to be redefined in every block.
3. Installation and a first haproxy.cfg
Installing HAProxy happens via the distribution's package manager, though newer versions are often obtained through additional repositories to benefit from features such as improved HTTP/2 support. After installation, haproxy -c -f /etc/haproxy/haproxy.cfg validates the configuration for syntax errors before the service is restarted, which should become mandatory before every deployment in production environments.
# Install HAProxy on Debian/Ubuntu
sudo apt update && sudo apt install -y haproxy
# Install HAProxy on RHEL/AlmaLinux
sudo dnf install -y haproxy
# Validate configuration syntax before reloading (always run this first)
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
# Reload without dropping active connections
sudo systemctl reload haproxy
# Enable on boot
sudo systemctl enable haproxy
# /etc/haproxy/haproxy.cfg — minimal working configuration
global
log /dev/log local0
maxconn 4096
user haproxy
group haproxy
defaults
mode http
log global
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
frontend web_front
bind *:80
default_backend app_servers
backend app_servers
balance roundrobin
option httpchk GET /healthz
server app1 10.0.0.11:80 check
server app2 10.0.0.12:80 check
server app3 10.0.0.13:80 check
This minimal setup accepts HTTP requests on port 80 and distributes them round robin across three backend servers, with check enabling an active health check for every server. Even with this small amount of configuration, a working load balancer is already operational, which is then extended with balancing strategy, SSL and monitoring.
4. Balancing algorithms compared
HAProxy supports several distribution algorithms, each better suited to different use cases. roundrobin distributes requests evenly in turn across all available servers and works well when all backend servers are roughly equally capable and requests generate similar load. leastconn, on the other hand, sends every new request to the server with the currently lowest number of open connections, which distributes load more fairly for long lived connections or heavily varying request durations.
The source algorithm consistently routes requests to the same server based on a hash of the client IP address, which enables a simple form of session persistence without cookies, but becomes problematic when many clients share the same IP behind a common NAT gateway. For weighted distribution, for instance when one backend server has more powerful hardware, every algorithm can additionally be given a weight parameter per server that controls the relative share of traffic.
| Algorithm | How it works | Best suited for |
|---|---|---|
roundrobin |
Even distribution in turn | Similar backends, short requests |
leastconn |
To server with fewest active connections | Long connections, uneven request duration |
source |
Hash of client IP, consistent mapping | Simple IP based persistence without cookies |
uri |
Hash of the request path | Cache friendly routing of identical URLs |
5. Health checks and automatic server removal
The option httpchk setting enables layer 7 health checks, where HAProxy periodically sends a real HTTP request to every backend server and evaluates the status code. If a server responds with an error code or does not respond at all, HAProxy marks it as down after a configurable number of failed checks and automatically removes it from rotation, without any human intervention needed.
It is important to build a dedicated health check endpoint that reflects real application health, for instance testing a database connection, instead of just serving a static page. An endpoint like /healthz that responds with status code 503 on a failed database connection ensures HAProxy correctly removes a server even when the web server itself is still running but the application behind it no longer works.
backend app_servers
balance leastconn
option httpchk GET /healthz
http-check expect status 200
default-server inter 3s fall 3 rise 2
server app1 10.0.0.11:80 check weight 100
server app2 10.0.0.12:80 check weight 100
server app3 10.0.0.13:80 check weight 50 backup
The parameter inter 3s defines the check interval, fall 3 the number of failed checks needed before removal and rise 2 the number of successful checks needed before recovery. The server flagged backup only receives traffic once all primary servers have failed, which works well for a cheaper emergency server that stays unused during normal operation.
6. Sticky sessions for stateful applications
When an application stores session data locally on the respective application server instead of a central session store such as Redis, every request from a client must consistently be routed to the same server. This technique is called a sticky session and is implemented in HAProxy via cookie based persistence, where HAProxy inserts an additional cookie into the response that identifies the assigned server.
Architecturally, a central session store in Redis or Memcached is almost always the better approach, since every backend server becomes stateless and HAProxy can freely switch between them without users losing their session. Cookie based sticky sessions remain a pragmatic solution for legacy applications where switching to central session storage is not possible in the short term.
backend app_servers
balance roundrobin
cookie SRVID insert indirect nocache
option httpchk GET /healthz
server app1 10.0.0.11:80 check cookie app1
server app2 10.0.0.12:80 check cookie app2
server app3 10.0.0.13:80 check cookie app3
7. SSL termination and layer 7 routing
A common use case for HAProxy is SSL termination: HAProxy accepts the encrypted HTTPS connection from the client, decrypts it, and forwards the request unencrypted or re encrypted to the backend servers. This centralizes certificate management in a single place instead of equipping every backend individually with certificates, significantly simplifying both certificate renewal and TLS configuration.
For layer 7 routing based on the host header or path, ACL rules in the frontend are used to distribute different domains or URL prefixes to different backend groups. This is especially useful when a single public IP address needs to serve multiple applications, for example a Magento shop under the main domain and a separate API under a subpath.
frontend web_front
bind *:443 ssl crt /etc/haproxy/certs/mironsoft.pem
mode http
# Route based on URL path prefix
acl is_api path_beg /api/
use_backend api_servers if is_api
default_backend app_servers
backend api_servers
balance leastconn
server api1 10.0.0.21:8080 check
server api2 10.0.0.22:8080 check
backend app_servers
balance roundrobin
server app1 10.0.0.11:80 check
server app2 10.0.0.12:80 check
8. Stats dashboard and monitoring
HAProxy ships with a built in stats dashboard, enabled via a dedicated port, that shows in real time the status of every backend server, current connection counts, error rates and response times. This dashboard is one of the fastest ways to immediately see, during a problem, which server is currently marked down or producing an unusual number of errors.
For automated monitoring, HAProxy also exposes a CSV export of the statistics through the same stats URL, which Prometheus, Grafana or custom scripts can consume. In production setups it is common to hide the stats port behind basic auth or an IP whitelist, since it would otherwise publicly expose detailed infrastructure information.
listen stats
bind *:8404
stats enable
stats uri /stats
stats auth admin:s3cr3tPassword
stats refresh 10s
9. HAProxy compared to nginx and cloud load balancers
HAProxy specializes in pure load distribution and offers deeper control over balancing algorithms, health checks and layer 7 routing than generic web servers that can also be used as load balancers. Open source nginx offers similar core functionality but less detailed health check options, though often with the more familiar configuration syntax for teams already running nginx as a web server. Cloud native load balancers, in turn, take on the entire operational responsibility, at ongoing cost, and offer less granular control over individual balancing details.
| Solution | Strength | Operational effort |
|---|---|---|
| HAProxy | Detailed health checks, stats dashboard, layer 4/7 | Self hosted, full control |
| nginx (open source) | Familiar syntax, good reverse proxy integration | Self hosted, simpler health checks |
| Cloud load balancer | Managed, automatic scaling | No self operation, ongoing cost |
For teams with their own Linux infrastructure and a desire for precise control over balancing behavior, HAProxy often remains the preferred choice. Combined with keepalived for the failure resistance of the HAProxy instance itself, a fully redundant setup emerges without dependency on a single cloud provider.
Mironsoft
Linux infrastructure, load balancing and server automation
Should traffic spikes stop bringing a server to its knees?
We design and operate HAProxy load balancers for Magento and PHP infrastructures, including health checks, SSL termination and monitoring, so your shop stays reliable even during traffic spikes.
Load balancer setup
HAProxy configuration with a fitting balancing algorithm
SSL & routing
Centralized SSL termination and layer 7 routing rules
Monitoring
Stats dashboard integration into existing monitoring
10. Summary
HAProxy solves two problems in a single configuration file: horizontal scaling across multiple backend servers and failure resistance through automatically removing unhealthy servers from rotation. The clear separation between frontend, backend and ACLs makes even complex layer 7 routing across multiple applications manageable, while balancing algorithms such as roundrobin and leastconn offer fitting distribution strategies for different load profiles.
Health checks against real application endpoints instead of plain port checks ensure HAProxy only serves genuinely functional servers. SSL termination centralizes certificate management in a single place, and the built in stats dashboard provides immediate visibility into the state of every backend server. Combined with keepalived for the redundancy of HAProxy itself, a fully failure resistant distribution layer emerges for production Linux infrastructures.
Load Balancer Setup with HAProxy — The essentials at a glance
Frontend/Backend
Clear separation between accepting requests and target server list, controlled via ACLs for layer 7 routing.
Health checks
Real application endpoints instead of plain port reachability, with fall/rise against flapping.
Balancing
roundrobin for similar servers, leastconn for uneven connection duration.
SSL & monitoring
Centralized SSL termination, stats dashboard with basic auth for ongoing visibility.