History
I started SSLB in 2011, in C, to solve a problem that had no good answer at the time. Three languages later the original idea is intact, and most of the vocabulary with it.
The problem I started with
In 2011 a load balancer working purely at TCP level could not make decisions on layer 7 information, and one designed for layer 7 was built around HTTP and poor at raw TCP. Sticky sessions, where they existed, usually tracked a route id in a particular format rather than the session the application had actually issued. And balancing non-HTTP traffic on layer 7 information — SIP, RTSP, a field inside a JSON body — was not on offer anywhere. I wanted one balancer that could do all of it, so I wrote one.
My first answer to that problem: a balancer that could see both layers at once rather than making me choose between them.
Porting it to C++ was where I made the decision everything since has been built around: rather than hardcoding balancing strategies, embed Lua and externalise the logic. Balancing decisions, layer 7 inspection and manipulation, and health checks all became scripts. That turned a load balancer into something closer to a scriptable proxy toolkit — as far as I know it was the only balancer that could do SIP NAT fixups.
A rewrite that keeps the idea and fixes what my C++ design could not do — and adds an admin API, which is what made a Kubernetes ingress controller possible at all.
What I changed in the rewrite
Sessions are streams, not packets
SSLBv2 handed a script one read() at a time and left it to guess where a message ended. A v3 session script gets a reassembled stream — read_line(), read_until(), peek() — so it no longer matters how a request was split across TCP segments or TLS records. That is the case I could never get right in v2.
A native HTTP module
HTTP/2 and HTTP/3 cannot sensibly be framed in a script, so Rust does it and calls the script once per parsed request. I also moved routing on host and path into the configuration, which takes the common case off the script path entirely.
Configuration that can change while running
An admin API, TLS-only and authenticated, that reconfigures a running balancer without dropping a listener. This is the change that made an ingress controller possible at all: a controller can watch Kubernetes and push, rather than rewriting a file and restarting.
Memory safety on a network-facing parser
This was my reason for changing language, more than any performance argument. The code that reads bytes from strangers is where a mistake is worst, and moving it somewhere that will not let me make that particular class of mistake was worth more than the speed.
What I kept
The vocabulary carries over deliberately: serverfarms, real servers, [Section] configuration files, get_user_data and set_user_data, SSLB_BACKEND_STATUS_UP. A v2 script is close to a v3 script, and where a v2 API was superseded the old one usually still works.
That was a goal rather than an accident. A rewrite that also rewrites its own interface asks everyone who depends on it to do the work twice, and I did not want to be the person who did that.