How to force a specific routing based on SNI in HAProxy?

I have the following HAProxy configuration:

listen sni-443
    bind *:443
    mode tcp

    timeout connect  4s
    timeout client   3m
    timeout server   3m
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }
    acl no-ssl req.ssl_hello_type 0

    use-server backend1.default.svc.cluster.local if !no-ssl { req_ssl_sni -i www.example.com }
    server  backend1.default.svc.cluster.local  10.96.245.95:443 weight 0

    use-server backend2.default.svc.cluster.local if !no-ssl { req_ssl_sni -i demo.example.com }
    server  backend2.default.svc.cluster.local  10.96.184.199:443 weight 0

If I visit www.example.com, everything is fine. But when I do so after having reloaded demo.example.com with high frequency (hammering on Shift-Ctrl-R in the browser), I end up at demo.example.com. Yes, exactly: I open www.example.com in the browser but HAProxy routes that to backend2 (which returns an error).

Apparently, HAProxy does not fully understand that the two services are not alternatives for load balancing but very distinct products. How can I ensure that www.example.com ends up with backend1?


This is an example from docs for req_ssl_sni:

tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
use_backend bk_allow if { req_ssl_sni -f allowed_sites }
default_backend bk_sorry_page

You probably need tcp-request inspect-delay set to something, because not setting it, means haproxy doesn't wait at all and has no idea what SNI was.
Longer explaination in docs for tcp-request inspect-delay