A simple round-robin load balancer written in Go. It distributes incoming HTTP requests across multiple backend servers, performs periodic health checks, and supports dynamic addition/removal of servers at runtime.
- Round-Robin Scheduling — Cycles through backend servers evenly, skipping any that are marked unhealthy.
- Health Checks — Pings each backend's
/healthendpoint every 10 seconds to detect failures and recoveries automatically. - Dynamic Server Updates — Add or remove backends on the fly via a
POST /update-serversAPI without restarting the load balancer. - Reverse Proxy — Uses Go's
httputil.ReverseProxyto forward requests transparently.
.
├── main.go # Load balancer (round-robin + health checks + reverse proxy)
├── backend.go # Simple backend server (responds with its port number)
└── README.md
- Go 1.18 or later
Build both the backend server and the load balancer:
go build -o backend backend.go
go build -o loadbalancer main.goOpen 4 separate terminals and start a backend on each port:
# Terminal 1
./backend -port 8001
# Terminal 2
./backend -port 8002
# Terminal 3
./backend -port 8003
# Terminal 4
./backend -port 8004In a 5th terminal, start the load balancer:
./loadbalancer -port 8080The load balancer will perform an initial health check and begin routing traffic across all 4 backends.
From any terminal, send a few requests and observe round-robin distribution:
curl http://localhost:8080
curl http://localhost:8080
curl http://localhost:8080
curl http://localhost:8080You should see responses cycling through the backends:
Hello from server on port 8001!
Hello from server on port 8002!
Hello from server on port 8003!
Hello from server on port 8004!
Close one of the backend terminals (e.g. the one running on port 8003) by pressing Ctrl+C. Now send more requests:
curl http://localhost:8080
curl http://localhost:8080
curl http://localhost:8080Within 10 seconds (the health check interval), the load balancer detects that 8003 is down and stops routing traffic to it. Requests are distributed only among the remaining healthy backends.
Restart the backend on port 8003:
./backend -port 8003The next health check will detect that 8003 is alive again and automatically add it back into the rotation — no restart needed.
You can also change the entire set of backends at runtime using the /update-servers endpoint:
curl -X POST http://localhost:8080/update-servers \
-H "Content-Type: application/json" \
-d '{"server_urls": ["http://localhost:8001", "http://localhost:8002"]}'This replaces the backend list with only ports 8001 and 8002. To add them all back:
curl -X POST http://localhost:8080/update-servers \
-H "Content-Type: application/json" \
-d '{"server_urls": ["http://localhost:8001", "http://localhost:8002", "http://localhost:8003", "http://localhost:8004"]}'- Startup — The load balancer initializes reverse proxies for each backend URL and runs an initial health check.
- Request Handling — On each incoming request, an atomic counter selects the next server index. If that server is unhealthy, it skips ahead to the next alive server.
- Health Checks — A background goroutine hits
/healthon every backend every 10 seconds, updating each server's alive status. - Dynamic Updates —
POST /update-serversaccepts a JSON body with a new list of server URLs, rebuilds the server pool, and triggers an immediate health check.