This guide explains how to configure HAProxy to maintain session persistence (also called sticky sessions) across multiple backend servers. With persistence, a client’s requests are always routed to the same server for the duration of a session, which is essential for applications that store session state locally (e.g., shopping carts, login tokens, or in-memory caches). You’ll learn the three main methods—source IP affinity, cookie-based stickiness, and session ID tracking—and how to implement them in your HAProxy configuration.
What You’ll Need
- A working HAProxy installation (version 1.5 or newer recommended).
- Access to the HAProxy configuration file (usually
/etc/haproxy/haproxy.cfg). - Basic familiarity with HAProxy frontend and backend sections.
- Knowledge of your application’s session mechanism (e.g., whether it uses cookies or URL parameters).
Step-by-Step
- Identify your session requirement. Determine whether your app needs sticky sessions at all. If your backend servers share session state (e.g., via a database or Redis), you may not need persistence. If not, choose one of the methods below.
- Method 1: Source IP affinity (simplest, but less reliable with NAT or proxies). In your backend section, add the
balance sourcedirective. This hashes the client’s IP address and consistently maps it to a server. Example:backend web_servers balance source server web1 192.168.1.10:80 check server web2 192.168.1.11:80 checkThis works well for internal networks but can break if clients come from a shared IP (e.g., corporate NAT).
- Method 2: Cookie-based stickiness (recommended for most web apps). Use HAProxy to insert a cookie that identifies the chosen server. Add the
cookiedirective in the backend andcookieparameter on each server line. Example:backend web_servers balance roundrobin cookie SERVERID insert indirect nocache server web1 192.168.1.10:80 cookie web1 check server web2 192.168.1.11:80 cookie web2 checkThe
insertoption makes HAProxy add aSet-Cookieheader if none exists.indirectremoves the cookie from the request before forwarding it to the server (so the server doesn’t see it).nocacheprevents caching proxies from storing the response. - Method 3: Session ID tracking (for apps that manage their own session ID). If your application already sets a session cookie (e.g.,
JSESSIONIDfor Java,PHPSESSIDfor PHP), you can tell HAProxy to stick on that cookie’s value. Use thestick-tableandstickdirectives:backend web_servers balance roundrobin stick-table type string len 32 size 100k expire 30m stick on req.cook(JSESSIONID) server web1 192.168.1.10:80 check server web2 192.168.1.11:80 checkThis stores the session ID in a table and maps it to the server that first served it. The
expireparameter controls how long the mapping is kept (adjust to match your session timeout). - Apply and test the configuration. After editing the config, run
haproxy -c -f /etc/haproxy/haproxy.cfgto validate syntax. Then reload HAProxy gracefully withsystemctl reload haproxy(orservice haproxy reload). Test by accessing your app from the same client and verifying that requests hit the same backend server (check server logs or use a test page that shows the server hostname). - Monitor and tune. Use
haproxy stats(enable the stats socket) to see stick-table usage and server hit counts. Adjust theexpiretime for stick-tables based on your session duration. For cookie methods, consider themaxidleandmaxlifeoptions to control cookie lifetime.
Common Mistakes
- Using source IP behind a proxy or load balancer. If clients go through a reverse proxy (like Cloudflare) or a NAT, all requests may appear to come from the same IP, causing all traffic to stick to one server. Use cookie-based stickiness instead.
- Forgetting
indirectoption. Without it, the server receives the cookie and may try to use it, potentially overriding its own session cookie. This can cause session conflicts. - Not setting
nocache. If a caching proxy stores the response with theSet-Cookieheader, it may serve the same cookie to different clients, breaking persistence. - Stick-table size too small. For high traffic, a small table can evict entries prematurely, causing a client to be redirected to a different server. Set a size that can hold the number of concurrent sessions.
- Mixing persistence methods. Using both source IP and cookie simultaneously can lead to unpredictable behavior. Stick to one method unless you have a specific reason.
Tips
- For cookie-based stickiness, use the
insertoption only when the client doesn’t already have the cookie. If the server sets its own cookie, useprefixorrewriteto avoid conflicts. - Set the
expiretime on stick-tables slightly longer than your session timeout to avoid premature loss of stickiness. - Use
option httpcloseoroption http-server-closeto ensure connections are handled correctly with cookies, especially in HTTP/1.0 scenarios. - Monitor the stick-table usage via the stats socket:
echo "show table" | socat stdio /var/run/haproxy.sock. This helps you adjust the size. - If you have a maintenance window, you can drain a server by setting its weight to 0, but sticky sessions will still route to it until the stick-table expires. Use
disableon the server line to stop new sessions.
Troubleshooting
- Sessions are not sticking. Check that the cookie is actually being set by HAProxy. Use
curl -Ito see the response headers. If noSet-Cookieappears, verify the backend configuration and that the server is up. - All traffic goes to one server. This often happens with source IP stickiness behind a NAT. Switch to cookie-based stickiness. Also check if the stick-table is full—if so, increase its size.
- Clients get a new server after a reload. HAProxy reloads clear stick-tables by default. Use the
stick-tablewith a persistent store (e.g.,peerssection) to share state across reloads and multiple HAProxy instances. - Server receives the cookie and complains. If your app sees the HAProxy cookie and tries to use it, add
indirectto the cookie directive. If the app sets its own cookie, useprefixto prepend the server name to the app’s cookie value. - Persistence works but only for a short time. The stick-table
expireis too short. Increase it to match your session length. - HAProxy fails to start with an error about stick-table. Ensure the
stick-tabletype matches the data you’re storing. For a cookie value, usetype string lenwith a length that covers your session ID length.
Frequently Asked Questions
Can I use both source IP and cookie stickiness?
Yes, but it’s not recommended. You can use balance source as a fallback if no cookie is present, but this requires a more complex configuration. In practice, choose one method that fits your environment.
How do I know which server a client is stuck to?
Check the server logs or enable a test page that outputs the server hostname. You can also use the stats socket to see the current stick-table entries.
What happens if a server goes down?
HAProxy will route new requests to other servers. For existing sessions, the stick-table entry will eventually expire, and the client will be reassigned. If you want immediate failover, you can configure option redispatch to allow rebalancing, but this may break the session.
Does session persistence work with HTTPS?
Yes, HAProxy can insert cookies over HTTPS. Ensure you have SSL termination configured on HAProxy (or pass-through) and the cookie is set securely (use the secure option in the cookie directive).
Can I share stick-tables between multiple HAProxy instances?
Yes, using the peers section. Define a peers section and reference it in the stick-table declaration. This synchronizes stick-table entries across HAProxy nodes, enabling persistence in a multi-node HAProxy setup.
How long should the stick-table expire be?
Set it to the maximum session duration you expect. For example, if sessions last 30 minutes, set expire 30m. If you’re unsure, start with 1 hour and adjust based on usage.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Campus Tech Innovation Hubs: What They Are
- Poco C51 Airtel Prepaid Locked Variant India?
- Jenkins vs GitHub Actions: Which CI/CD Fits Your Team?
- Turn Off Backup Encryption in iTunes?
- Shared VPS Hosting: Is It Better?
- Disk Defrag Pro: What It Does and Whether You Need It