I wanted to understand how real load balancers work under the hood, so I built one in Go using only the standard library.
A minimal implementation that still incorporates essential building blocks of production-style load balancers:
- Reverse proxy using httputil.ReverseProxy
- Atomic round-robin load balancing (no mutex)
- Active health checks (runs every 10s, concurrent probing)
- Automatic failover + retry on backend failure
- Structured request logging
- Skips unhealthy backends dynamically
Architecture:
Client → Load Balancer (:8080) → Backend servers (:9001, :9002, :9003)
How it works:
- Each request is forwarded through a reverse proxy
- A global atomic counter distributes traffic (round-robin)
- Health checker continuously probes /health on each backend
- If a backend fails → it’s marked down and skipped
- Proxy retries request on the next available backend
One thing I found interesting:
Go’s httputil.ReverseProxy gives you hooks like ErrorHandler, which makes it possible to implement retry/failover cleanly before any response is sent.
Example behavior:
- Kill one backend → traffic automatically reroutes
- Restart it → it gets picked up again after health check
Everything is built with Go stdlib — no frameworks, no external deps.
Repo:
https://github.com/pigglegiggle/load_balancer
Would love feedback on:
- architecture decisions
- better load balancing strategies (least connections, etc.)
- production improvements
Top comments (0)