Operations 40 min read

Master HAProxy ACLs: Dynamic Routing, Traffic Splitting, and Real‑Time Updates

This comprehensive guide explains HAProxy ACL fundamentals, showcases powerful routing patterns such as multi‑domain, path‑based, header‑based, and canary releases, provides step‑by‑step configuration examples, scripts for runtime adjustments, best‑practice recommendations, troubleshooting tips, and monitoring strategies for production‑grade load balancing.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Master HAProxy ACLs: Dynamic Routing, Traffic Splitting, and Real‑Time Updates

Overview

HAProxy ACLs allow fine‑grained traffic routing based on host, path, headers, cookies, IP, etc. They are essential for micro‑service, multi‑tenant and API‑gateway scenarios.

Key Features

Declarative rules : define a condition once and reuse it.

Rich matching methods : exact, prefix, suffix, regex, IP range, and more.

Value extraction : URL, headers, cookies, query parameters, SSL information.

Logical composition : combine ACLs with AND, OR, NOT.

Runtime updates : modify ACLs and map files via the Runtime API without reloading.

Typical Use Cases

Multi‑domain routing

Path‑based routing

Canary / A‑B testing (percentage or header‑based)

Blue‑green deployments

IP whitelist / blacklist

Rate limiting per source IP

Maintenance mode

Environment Requirements

HAProxy 3.0.5 or newer

Linux (Rocky 9.4 or Ubuntu 24.04 LTS) socat for Runtime API communication

ACL Syntax

acl <name> <fetch> [flags] [pattern]

Common fetch methods: path, path_beg, hdr(name), cook(name), src, method. Common flags: -i (case‑insensitive), -f (read values from a file), -m with str, beg, end, sub, reg, found.

Configuration Examples

Multi‑Domain Routing

frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
    acl host_api   hdr(host) -i api.company.com
    acl host_web   hdr(host) -i www.company.com
    use_backend api_servers   if host_api
    use_backend web_servers   if host_web
    default_backend web_servers

backend api_servers
    balance roundrobin
    server api1 192.168.1.11:8080 check
    server api2 192.168.1.12:8080 check

Path‑Based Routing

acl path_api_users   path_beg /api/v1/users
acl path_api_orders  path_beg /api/v1/orders
use_backend user_service    if path_api_users
use_backend order_service   if path_api_orders

Header‑Based Canary Release

acl gray_header hdr(X-Gray-Release) -i true
use_backend canary_servers if gray_header
default_backend stable_servers

Traffic Splitting by Percentage

# 10 % canary traffic
acl is_canary rand(100) lt 10
use_backend canary_servers if is_canary
use_backend stable_servers  if !is_canary

Dynamic Map Files

Map files store key‑value pairs that can be updated at runtime.

# /etc/haproxy/maps/user_canary.map
user_001 canary
user_002 canary
user_003 canary

Reference in configuration:

http-request set-var(req.canary) var(req.user_id),map(/etc/haproxy/maps/user_canary.map,stable)
acl is_canary var(req.canary) -m str canary
use_backend canary_servers if is_canary

Runtime Update Scripts

Adjust canary ratio without reload:

#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
set_canary_ratio() {
    local ratio=$1
    echo "set map /etc/haproxy/maps/canary_ratio.map default $ratio" | socat stdio $SOCKET
}
# Example: ./script.sh set 20   # 20 % canary traffic

Blue‑Green Deployment

Active environment stored in a map file ( active_env.map). The frontend reads the map and routes accordingly.

frontend http_front
    bind *:80
    http-request set-var(req.active_env) str(default),map(/etc/haproxy/maps/active_env.map,blue)
    use_backend blue_servers   if { var(req.active_env) -m str blue }
    use_backend green_servers  if { var(req.active_env) -m str green }
    default_backend blue_servers

Switch script (simplified):

#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
ENV_MAP="/etc/haproxy/maps/active_env.map"

switch_env() {
    local target=$1
    echo "set map $ENV_MAP default $target" | socat stdio $SOCKET
}
# Usage: ./blue_green_switch.sh switch blue|green

Best Practices

Naming convention : host_ for domain ACLs, path_ for URL ACLs, is_ for boolean checks, has_ for existence checks.

Order optimization : place the most frequently matched and cheapest checks first; move expensive regex or body parsing to the end.

Use map files for large or frequently changing lists (IP blacklists, tenant routing, canary assignments). They can be updated via the Runtime API.

Avoid redundant extraction : store a value in a variable once and reuse it in multiple ACLs.

Common pitfalls : missing -i makes host matching case‑sensitive; path_beg /api also matches /api123 – add a trailing slash for precise matching; escape dots in regular expressions; use canonical header names.

Troubleshooting & Monitoring

ACL Debug Commands (Bash helper)

#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
show_acls() { echo "show acl" | socat stdio $SOCKET; }
test_acl() { local id=$1 val=$2; echo "get acl #$id $val" | socat stdio $SOCKET; }
# Usage examples:
#   ./debug_acl.sh list
#   ./debug_acl.sh test 12 "hdr(host) -i example.com"

Request Tracing

Add a debug header ( X-Debug: true) and return routing information in response headers. This does not require a configuration reload.

acl debug_mode hdr(X-Debug) -i true
http-response set-header X-Matched-Host %[hdr(host)]   if debug_mode
http-response set-header X-Matched-Path %[path]        if debug_mode
http-response set-header X-Backend-Name %[be_name]    if debug_mode
http-response set-header X-Server-Name %[srv_name]    if debug_mode

Prometheus Metrics

Export backend request rates and canary traffic proportion. Example alert when canary traffic exceeds 20 %:

alert: CanaryTrafficRatioHigh
expr: sum(rate(haproxy_backend_http_requests_total{backend="canary_servers"}[5m]))
      / sum(rate(haproxy_backend_http_requests_total[5m])) > 0.2
for: 5m
labels:
  severity: warning

Backup Script

#!/bin/bash
BACKUP_DIR="/data/backups/haproxy_acl"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR/$DATE"
cp /etc/haproxy/haproxy.cfg "$BACKUP_DIR/$DATE/"
cp -r /etc/haproxy/maps "$BACKUP_DIR/$DATE/"
SOCKET="/run/haproxy/admin.sock"
if [ -S "$SOCKET" ]; then
    echo "show acl" | socat stdio $SOCKET > "$BACKUP_DIR/$DATE/runtime_acls.txt"
    for map in /etc/haproxy/maps/*.map; do
        name=$(basename $map)
        echo "show map $map" | socat stdio $SOCKET > "$BACKUP_DIR/$DATE/runtime_${name}.txt"
    done
fi
cd "$BACKUP_DIR"
tar -czf "${DATE}.tar.gz" "$DATE"
rm -rf "$DATE"
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete

Real‑World Cases

Multi‑Tenant SaaS Routing

Extract tenant ID from sub‑domain, look up tenant_routing.map to select a backend pool, and optionally apply a tenant‑specific canary map.

# Extract tenant ID
http-request set-var(req.tenant_id) hdr(host),regsub(\.saas\.company\.com$,)
# Map tenant → backend
http-request set-var(req.tenant_backend) var(req.tenant_id),map(/etc/haproxy/maps/tenant_routing.map,shared_pool)
# Tenant‑level canary
http-request set-var(req.tenant_canary) var(req.tenant_id),map(/etc/haproxy/maps/tenant_canary.map,stable)
acl tenant_is_canary var(req.tenant_canary) -m str canary
use_backend canary_servers if tenant_is_canary
use_backend %[var(req.tenant_backend)]

Blue‑Green Deployment Automation

Map file active_env.map stores the current environment. A Bash script validates backend health, updates the map atomically via the Runtime API, and optionally sends a webhook.

# Switch environment (blue or green)
switch_env() {
    local target=$1
    # Verify at least two healthy servers in the target backend
    healthy=$(echo "show stat" | socat stdio $SOCKET | grep "${target}_servers" | grep UP | wc -l)
    if [ "$healthy" -lt 2 ]; then
        echo "Not enough healthy servers in $target, abort"
        exit 1
    fi
    echo "set map /etc/haproxy/maps/active_env.map default $target" | socat stdio $SOCKET
    # Optional webhook notification
    curl -s -X POST http://alert-api/webhook -d "{\"message\":\"Switched to $target\"}"
}
# Usage: ./deploy_switch.sh blue

Summary

ACLs are the core of HAProxy traffic control; mastering them enables flexible routing.

Combine fetch methods and flags to express precise matching conditions.

Map files provide a runtime‑updatable data source for tenant routing, canary assignments, IP lists, and more.

Optimize ACL order and avoid heavy regex to keep latency low.

Instrument ACL usage with Prometheus metrics and enable debug headers for fast troubleshooting.

Load Balancingblue-green deploymentDynamic Routingtraffic splittingACLHAProxycanary release
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.