Load Balancer
Implement an in-memory LoadBalancer that distributes requests across a pool of backend servers
Stage 1 - Clarify Requirements
- "A LoadBalancer, in-memory, that takes a request and route it to the appropriate host, that will be picked up from a pool of hosts"
-
It has state, implement it as a class with a couple of methods and attributes
-
targets (A)
- What is the format of a target? String?
- Maximum capacity?
-
default capacity?
-
register (M)
- Register a duplicate: throw or false?
-
Register on max capacity: throw or false?
-
pick (M)
- what strategy to use to decide which server to pick? Random?
- The strategy is plugged via constructor?
-
On Empty servers: throw?
-
Handle concurrency issues and race conditions here from multiple threads?
- Specially on the register and pick operations
I'll use the Strategy pattern —
LoadBalancerholds aStrategythat picks a server from the current pool. Round-robin needs internal state (an index), so the strategy is stateful. I'll inject the strategy via the constructor; default round-robin. For thread safety, athreading.Lockguarding the pool. Pool islist[str]because order matters for round-robin.registeris O(1) amortised,unregisteris O(n) (list.remove),getis O(1).
Stage 2 — Class Skeleton and simple methods
- Sketch the class skeleton and its constructors and methods
- Develop simple tests for each method before coding it, and more tests to enrich it along the implementation
Stage 3 — Strategies
Make the picking logic interchangeable
Likely follow-ups: weighted random, least-connections, sticky sessions.
Stage 4 — Concurrency
The load balancer must be safe to call from multiple threads. Mutations and reads should not race.
Phase 5 — Reflect & optimise
-
Sticky sessions: hash client ID modulo pool size.
pool[hash(client_id) % len(pool)]; doesn't survive resize without consistent hashing -
Health checks: background task pings each server every X seconds; mark dead, exclude"
-
Lock-free pick(): copy-on-write list, atomic reference swap
-
Distributed: consistent hashing or service discovery (Consul, etcd, k8s endpoints)
-
Other strategies: weighted round-robin (prefix sums + bisect), least-connections (track in-flight per server with a heap),