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:
- These cover 90%+ of production use cases
- Other protocols often require dedicated proxies (e.g., FTP passive mode complexities)
- 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.