HAProxy load balancing with sticky sessions based on request body

Integrating systems you have no influence on needs a lot of workarounds. Recently we could not scale Python service consuming SOAP messages with a new hardware. It just didn’t benefit from more processing cores. On the other hand (and this happens often with older software) setting up several instances gave almost linear scalability. Only thing left – configure a loadbalancer and we are done.

Easier said than done. We had to make sure messages are loadbalanced but also that all messages related to given customer USSD conversation always hit the same backend service. So, we had to use application layer information to configure sticky sessions. This is not straightforward in HAProxy when you have to look into http payload and parse some specific information. We used HAProxy 1.6 and simple LUA script to do just that:

core.Alert("LUA script parsing SOAP element loaded");

function parseElement(txn, salt)

    local payload = txn.req:dup()

    -- parses integer value from element named "element"
    local value = string.match(string.match(payload, "element>%d+<"), "%d+")
    core.Info("value: " .. value)
    return value

-- register HAProxy "fetch"
core.register_fetches("parseElement", parseElement)

Put this script into a file and it can be loaded in HAProxy configuration using lua-load directive.

Script registers new HAProxy fetch which can be used to configure session stickiness.

balance roundrobin
stick-table type string size 30k expire 30m
stick on "lua.parseElement" table nodes

You have to also make sure all payload is loaded before you start parsing it. This can be achieved with option http-buffer-request configuration directive.

6 thoughts on “HAProxy load balancing with sticky sessions based on request body”

  1. thanks for the write up! can you post your entire haproxy.conf? I am getting this error:

    [ALERT] 213/092637 (51802) : Proxy ‘web-backend’: unable to find stick-table ‘nodes’.
    [ALERT] 213/092637 (51802) : Fatal errors found in configuration.

  2. You might want to change the string.match to this:

    local _, _, value = string.find(payload, “element>(%d+)<")

  3. I have noticed you don’t monetize your blog, don’t waste your traffic, you can earn extra cash
    every month because you’ve got hi quality content. If you want to
    know how to make extra bucks, search for: Mertiso’s tips best adsense

  4. I have checked your website and i have found some duplicate
    content, that’s why you don’t rank high in google’s search results, but there is a
    tool that can help you to create 100% unique content, search for; Boorfe’s tips unlimited content

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.