Model request dispatch as an injected transport so selection, connection tracking, and health checks are all exactly testable with pinned sequences - no sockets, no flakiness. Every lesson is one concrete spec with exact values: round-robin wrapping from the last backend back to the first, weighted 3-to-1 cycling A,A,A,B, least-connections breaking a tie deterministically, power-of-two-choices taking the less loaded of two, ejection after exactly three consecutive failures, recovery after two good probes, an all-down pool returning a clear error instead of hanging, and a draining backend excluded from new work while its in-flight count still drains to zero.
Over 25 lessons you build a working load balancer from scratch, designed so every decision it makes is exactly testable. The trick is an injectable transport: instead of opening real sockets, the balancer dispatches each request through a function you supply that maps a chosen backend to a response. That keeps selection order, connection counts, and health-state transitions all deterministic - the same balancer core runs in any language, and every lesson pins an exact sequence, count, or state.
You start with a backend pool you can add to, remove from, and filter to the healthy members. Then you build the selection algorithms one per lesson - round-robin with its wrap-around cursor, weighted round-robin, seeded random, least-connections, power-of-two-choices, and sticky sessions - each with its exact dispatch order pinned. On top of that you track active connections through dispatch (up on the way in, down on completion, even on error), and drive a health-check state machine that ejects a backend after a run of failures, probes backends out of band, and brings one back after enough successes. The capstone routes a scripted request stream across backends that flap and drain, asserting the exact backend chosen for every request and that every connection count returns to zero.
This is a teaching-grade layer-7 balancer built around the classic algorithms in HAProxy, NGINX, and Envoy: it selects a healthy backend, tracks load, and reacts to health signals. It is honest about what it stops short of - the graded core dispatches through an injected transport rather than real sockets (the finalize pass adds a runnable TCP reverse proxy), it is single-goroutine with no locking, and it uses simple session-table stickiness rather than a consistent-hashing ring (that is its own separate project). That is the honest core that production proxies extend with real I/O, concurrency, and richer routing.
A load balancer spreads work across a set of backends, so the first thing to model is one backend - an address it forwards to and whether it is currently up. Today you build that type and toggle its health.
Create a backend with an id and address that starts up, and can be marked down and up again.
Every load balancer sits in front of a group of backends - the real servers that do the work. A backend is mostly an address to forward a request to, plus a little state the balancer keeps about it. The most important piece of that state is whether the backend is healthy right now, because a balancer must never send new work to a server it believes is down.
Model the health as a small status value rather than a bare boolean. Today it
only needs Up and Down, but later in the project a backend can also be
Draining (finishing its in-flight work while taking no new requests), and an
enum leaves room for that third state without a rewrite. Start every backend Up;
the health-check chapter is where status starts changing on its own.
// status is an enum so DRAINING can join UP and DOWN latertype Status intconst ( Up Status = iota; Down )type Backend struct {ID, Addr stringstatus Status}func NewBackend(id, addr string) *Backend { return &Backend{ID: id, Addr: addr, status: Up} }func (b *Backend) IsUp() bool { return b.status == Up }func (b *Backend) MarkDown() { b.status = Down }func (b *Backend) MarkUp() { b.status = Up }
The balancing, health-checking, and routing logic is genuinely complete and runs end to end - the finalize pass wires the injected-transport core to real HTTP sockets in a runnable reverse proxy (cmd/lb) with live active health probes, failover, and a 503 when everything is down - but it is a minimal string-in, string-out proxy with no header, method, or status passthrough, the weighted round-robin schedule is frozen at construction, and a Backend is not synchronized for the concurrent traffic a real listener drives.
The reference for real-world balancing: the balance algorithms (roundrobin, static-rr, leastconn, source, random), backend weights, and the check / rise / fall health-check parameters this project models directly.
The admin-level view of round-robin, weighted, least-connections, and hash-based methods, plus passive health checks (max_fails / fail_timeout) - the same mechanisms built here from first principles.
The Envoy author's overview of L4 vs L7 balancing, the load-balancing algorithm zoo, and active vs passive health checking - the best single orientation to the problem space.
Production semantics for the algorithms and the health-check state machine (active probing, outlier detection / passive ejection, healthy panic threshold) - read alongside the health-checking chapter.
The paper behind power-of-two-choices: why sampling two backends and taking the less loaded gives almost the balance of tracking every backend, at a fraction of the cost.
A short, intuitive writeup of why two random choices beats one, and where it beats even global least-connections under stale load information - the practical companion to the paper.