HAProxy's ACL (Access Control List) system combined with cookie parsing makes it possible to route traffic to specific backend servers based on cookie values. This is particularly useful for:
- Sticky sessions implementation
- A/B testing deployments
- Multi-tenant architectures
- Canary releases
Here's a complete configuration example for routing traffic based on the "loginCreds" cookie:
frontend http-in bind *:80 acl company_a req.cook(loginCreds) -m sub CompanyA acl company_b req.cook(loginCreds) -m sub CompanyB use_backend servers_a if company_a use_backend servers_b if company_b default_backend servers_default backend servers_a server serverA 192.168.1.10:80 check backend servers_b server serverB 192.168.1.11:80 check backend servers_default server serverDefault 192.168.1.12:80 check
For more complex scenarios, you can use regex matching:
acl premium_user req.cook(loginCreds) -m reg :Premium$ use_backend premium_servers if premium_user
Or combine multiple conditions:
acl vip_user req.cook(loginCreds) -m sub CompanyA req.cook(userType) -m str VIP use_backend vip_servers if vip_user
When implementing cookie-based routing:
- Cookie parsing adds slight overhead - benchmark with your traffic patterns
- Consider using
req.cook_val()
instead ofreq.cook()
for exact matches - For high-traffic sites, pre-compile ACL patterns using
-m reg
with simple patterns
Common issues and solutions:
# Check cookie values in logs: capture request header Cookie len 512 # Debug ACL matches: http-request set-var(txn.debug) req.cook(loginCreds) log-format %[var(txn.debug)]
Remember to test your configuration with haproxy -c -f /etc/haproxy/haproxy.cfg
before applying changes.
HAProxy's cookie-based routing is a game-changer for session persistence and A/B testing scenarios. When you need to maintain user stickiness to specific backend servers based on session cookies, this approach provides an elegant solution.
Here's the essential HAProxy configuration to achieve cookie-based routing:
frontend http-in
bind *:80
acl is_companyA req.cook(loginCreds) -m sub :CompanyA
acl is_companyB req.cook(loginCreds) -m sub :CompanyB
use_backend servers_companyA if is_companyA
use_backend servers_companyB if is_companyB
default_backend servers_default
backend servers_companyA
cookie SERVERID insert indirect nocache
server serverA 192.168.1.10:80 check cookie serverA
backend servers_companyB
cookie SERVERID insert indirect nocache
server serverB 192.168.1.20:80 check cookie serverB
backend servers_default
server default1 192.168.1.30:80 check
For more complex cookie matching logic, consider these approaches:
# Match exact cookie value
acl is_john req.cook(loginCreds) John:CompanyA
# Regex pattern matching
acl is_companyA_user req.cook(loginCreds) -m reg :CompanyA$
# Cookie presence check
acl has_login_cookie req.cook(loginCreds) -m found
When implementing cookie-based routing, remember:
- Always configure proper fallback mechanisms
- Consider adding health checks for your backend servers
- Test cookie handling with different browser behaviors
- Monitor the stickiness ratio to ensure proper balancing
Enable debugging in HAProxy with:
global
log /dev/log local0 debug
frontend http-in
capture request header Cookie len 64
This will help track cookie values being processed by HAProxy.