Load Balancing with HAProxy and Health Checks
Configure HAProxy as a high-performance load balancer with active health checks, sticky sessions, and SSL termination for resilient service distribution
Distribute incoming traffic across multiple backend servers using HAProxy, a high-performance TCP/HTTP load balancer. The solution below covers round-robin distribution, active health checks, sticky sessions, and SSL termination for production-grade resilience.
When to Use This
- You run multiple application instances and need to distribute traffic evenly. See Health Check Endpoint for backend health probes.
- Services must be automatically removed from rotation when unhealthy. See Circuit Breaker for failure isolation.
- SSL termination should happen at the edge, not on each application server. See Nginx Reverse Proxy for edge proxy patterns.
Solution
1. Basic HAProxy Configuration
# haproxy.cfg
global
log stdout local0
maxconn 4096
defaults
mode http
timeout connect 5s
timeout client 30s
timeout server 30s
option httpchk GET /health
frontend web_frontend
bind *:80
default_backend app_servers
backend app_servers
balance roundrobin
server web1 10.0.1.10:3000 check
server web2 10.0.1.11:3000 check
server web3 10.0.1.12:3000 check
2. Active Health Checks
backend app_servers
balance roundrobin
option httpchk GET /health
# Mark as down after 2 failed checks; up after 3 successes
default-server inter 5s fall 2 rise 3
server web1 10.0.1.10:3000 check
server web2 10.0.1.11:3000 check
server web3 10.0.1.12:3000 check
3. Sticky Sessions with Cookies
backend app_servers
balance roundrobin
cookie SERVERID insert indirect nocache
server web1 10.0.1.10:3000 check cookie web1
server web2 10.0.1.11:3000 check cookie web2
server web3 10.0.1.12:3000 check cookie web3
4. SSL Termination
frontend web_frontend
bind *:443 ssl crt /etc/ssl/certs/site.pem
http-request redirect scheme https unless { ssl_fc }
default_backend app_servers
5. Stats Dashboard
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
How It Works
- Frontend listens on a port and receives client connections
- Backend defines the pool of servers and balancing algorithm
- Health checks send periodic requests; failing servers are removed
- Cookie insertion pins a user to a specific backend for session affinity
Variation: Weighted Load Balancing
backend app_servers
balance roundrobin
server web1 10.0.1.10:3000 check weight 3
server web2 10.0.1.11:3000 check weight 2
server web3 10.0.1.12:3000 check weight 1
Production Considerations
- Run HAProxy in active-passive with keepalived for failover
- Use
leastconnfor long-lived WebSocket connections - Enable compression with
compression algo gzip
Common Mistakes
- Forgetting to expose a
/healthendpoint in applications - Using source IP affinity behind NAT where all clients share one IP
- Not monitoring the stats page for backend degradation
Performance Tips
- Tune
maxconnbased on available memory. Each connection uses ~200 bytes. For 10K connections, allocate ~2MB:
global
maxconn 10000
nbproc 4 # Use multiple processes for multi-core CPUs
- Use
nbthreadfor multi-threaded mode. HAProxy 2.0+ supports threads:
global
nbthread 4
cpu-map auto:1/1-4 0-3
- Enable
splice-requestandsplice-responsefor TCP. Uses kernel splice for zero-copy forwarding:
defaults
mode tcp
option splice-request
option splice-response
- Use
tune.ssl.default-dh-paramfor SSL performance. Set to 2048 or higher:
global
tune.ssl.default-dh-param 2048
- Monitor with HAProxy stats socket. Export metrics to Prometheus for alerting:
# Enable stats socket
echo "stats socket /var/run/haproxy.sock mode 660 level admin" >> haproxy.cfg
# Query stats
echo "show info" | socat /var/run/haproxy.sock -
echo "show servers state" | socat /var/run/haproxy.sock - Frequently Asked Questions
How is this different from Nginx?
HAProxy specializes in layer 4/7 load balancing with superior health check granularity. Nginx is a general-purpose web server that also proxies.
Can I use HAProxy with Docker?
Yes. Use the official haproxy image and mount your haproxy.cfg as a volume.
Related Resources
Ambassador Pattern for Resilient Remote Service Access
Add a local ambassador that handles retries, circuit breaking, and monitoring when calling remote services, keeping the client simple and the service logic pure
RecipeConfigure Nginx as a Reverse Proxy and API Gateway
How to use Nginx as a reverse proxy for backend services, implement load balancing, SSL termination, and rate limiting for production API gateways
PatternCircuit Breaker Pattern
Prevent cascading failures by stopping requests to failing services. An architectural pattern for resilient distributed systems.
RecipeAWS CLI Bash Scripts
Automate AWS resource provisioning with bash and AWS CLI
RecipeCloud Cost Optimization Recipe
Reduce cloud infrastructure costs with right-sizing, reserved instances, spot instances, and automated resource scheduling across AWS, GCP, and Azure.
RecipeProvision an AWS VPC with Terraform
How to use Terraform to provision a production-ready AWS VPC with public and private subnets, NAT gateways, and security groups