HAProxy Mode Selection: Understanding TCP vs HTTP for Protocol-Specific Load Balancing


2 views

When configuring HAProxy, the choice between mode tcp and mode http fundamentally changes how the proxy handles traffic:


# TCP mode (Layer 4)
backend tcp_backend
    mode tcp
    server server1 192.168.1.10:3306 check
    
# HTTP mode (Layer 7) 
backend http_backend
    mode http
    http-request set-header X-Forwarded-Port %[dst_port]
    server server1 192.168.1.20:80 check

Port numbers alone don't determine protocol behavior. While HTTP typically uses port 80/443, the mode selection enables critical functionality:

  • TCP mode: Pure byte stream forwarding with:
    • Zero protocol awareness
    • Minimal overhead
    • Suitable for databases, custom protocols
  • HTTP mode: Enables:
    • Header manipulation
    • Cookie-based persistence
    • Path-based routing
    • HTTP-specific logging

MySQL Load Balancing (TCP Mode):


frontend mysql_frontend
    bind *:3306
    mode tcp
    default_backend mysql_servers

backend mysql_servers
    mode tcp
    balance leastconn
    server db1 10.0.0.1:3306 check
    server db2 10.0.0.2:3306 check backup

Web Application (HTTP Mode):


frontend web_frontend
    bind *:80
    mode http
    acl is_api path_beg /api
    use_backend api_servers if is_api
    default_backend web_servers

backend web_servers
    mode http
    cookie SERVERID insert nocache
    server web1 10.0.1.1:80 cookie s1 check
    server web2 10.0.1.2:80 cookie s2 check

backend api_servers
    mode http
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    server api1 10.0.2.1:8080 check

HAProxy focuses on HTTP/TCP because:

  1. These cover 90%+ of production use cases
  2. Other protocols often require dedicated proxies (e.g., FTP passive mode complexities)
  3. TCP mode serves as escape hatch for custom protocols

When configuring HAProxy, the choice between TCP and HTTP modes isn't just about port selection - it's about protocol awareness. While HTTP traffic indeed runs over TCP, setting mode http enables layer 7 features that mode tcp simply can't provide.

HTTP mode unlocks advanced load balancing features:

frontend web-in
    mode http
    bind *:80
    acl url_blog path_beg /blog
    use_backend blog_servers if url_blog
    default_backend web_servers

This configuration demonstrates HTTP-specific routing based on URL paths, impossible in TCP mode.

TCP mode shines for non-HTTP protocols or when you need pure layer 4 forwarding:

frontend mysql-in
    mode tcp
    bind *:3306
    default_backend mysql_cluster

Here we're load balancing MySQL connections where HTTP parsing would be irrelevant.

Choosing port 80 with TCP mode doesn't magically enable HTTP features. The mode determines how HAProxy processes the traffic, not the destination service. A TCP listener on port 80 would forward raw bytes without understanding HTTP headers, methods, or status codes.

HAProxy focuses on HTTP because:

  • HTTP/S represents the majority of web traffic
  • Protocol-specific optimizations require deep parsing capabilities
  • Other protocols often work fine with basic TCP load balancing

For specialized protocols, consider protocol-aware proxies (like pgpool for PostgreSQL) or HAProxy's mode tcp with custom checks.

HTTP mode with SSL termination:

frontend https-in
    mode http
    bind *:443 ssl crt /etc/ssl/certs/example.pem
    http-request set-header X-Forwarded-Proto https
    default_backend web_servers

TCP mode for SSH traffic:

frontend ssh-in
    mode tcp
    bind *:22
    default_backend ssh_servers
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

Check your mode selection by running:

echo "show info" | sudo socat stdio /run/haproxy/admin.sock | grep -i mode

Remember that HTTP mode adds about 5-10% overhead compared to TCP mode due to header processing.