PrepZone Logo
PrepZone

Load Balancers

Spread traffic across servers with L4/L7 balancers, health checks and sticky sessions.

Read these first

Why StreamHub needed a load balancer

At ~20K DAU, StreamHub's single API instance hit connection limits during peak evening viewing. Adding an Application Load Balancer (ALB) in front of four identical pods removed the bottleneck without code changes.

AWS ALB → EKS traffic path

TLSCLIENT
UsersHTTPS requests
NETWORK
Route 53alias → ALB
NETWORK
AWS ALBtarget group
COMPUTE
EKS pod 1streamhub-api
COMPUTE
EKS pod 2streamhub-api
COMPUTE
EKS pod NHPA scaled
L7 ALB terminates TLS, health-checks targets, and fans out to stateless pods.

StreamHub production architecture (AWS)

HTTPSstaticmissAPICLIENT
Mobile / WebStreamHub cli…
NETWORK
Route 53GeoDNS routing
NETWORK
CloudFrontCDN + WAF edge
NETWORK
AWS ALBTLS terminati…
NETWORK
API GatewayJWT · rate li…
STORAGE
Amazon S3media origin
COMPUTE
Amazon EKSAPI · auth · …
DATABASE
ElastiCachesessions · ho…
DATABASE
RDS Postgresprimary + rep…
INTEGRATION
Amazon MSKdomain events
ANALYTICS
OpenSearchstream discov…
OPS
CloudWatchmetrics · X-R…
End-to-end path from user to data — reference this when placing any new service.

Load balancer responsibilities

  • Distribute requests — round-robin, least connections, weighted, or hash-based.
  • Health checks — remove unhealthy backends automatically.
  • TLS termination — decrypt HTTPS at the edge, forward HTTP internally.
  • Sticky sessions — route same client to same backend when needed.
  • Path-based routing — /api/* to API pool, /admin/* to admin pool.

Layer 4 vs Layer 7

AspectL4 (Transport)L7 (Application)
Routes onIP + portURL path, headers, cookies
AwarenessTCP/UDP onlyHTTP headers, WebSocket upgrade
ExamplesAWS NLB, HAProxy TCP modeAWS ALB, NGINX, Envoy
StreamHubInternal DB proxy (rare)Public API entry point
  • Routes on

    L4 (Transport)IP + port
    L7 (Application)URL path, headers, cookies
  • Awareness

    L4 (Transport)TCP/UDP only
    L7 (Application)HTTP headers, WebSocket upgrade
  • Examples

    L4 (Transport)AWS NLB, HAProxy TCP mode
    L7 (Application)AWS ALB, NGINX, Envoy
  • StreamHub

    L4 (Transport)Internal DB proxy (rare)
    L7 (Application)Public API entry point

Most HTTP APIs use L7 balancers for path routing and header inspection.

Load balancing algorithms

AlgorithmBehaviourWhen to use
Round-robinCycle through backends in orderEqual-capacity stateless servers
Least connectionsSend to fewest active connectionsLong-lived requests, varying work
WeightedProportional traffic by weightCanary deploys, mixed instance sizes
IP hashSame client IP → same backendSimple stickiness without cookies
Consistent hashHash on header/keyCache-friendly routing (advanced)
  • Round-robin

    BehaviourCycle through backends in order
    When to useEqual-capacity stateless servers
  • Least connections

    BehaviourSend to fewest active connections
    When to useLong-lived requests, varying work
  • Weighted

    BehaviourProportional traffic by weight
    When to useCanary deploys, mixed instance sizes
  • IP hash

    BehaviourSame client IP → same backend
    When to useSimple stickiness without cookies
  • Consistent hash

    BehaviourHash on header/key
    When to useCache-friendly routing (advanced)
Java
# AWS ALB target group — StreamHub API
target_group: streamhub-api-tg
protocol: HTTP
port: 8080
health_check:
  path: /health
  interval: 15
  healthy_threshold: 2
  unhealthy_threshold: 3
algorithm: least_outstanding_requests

Health checks and graceful shutdown

Backends that fail health checks are drained from the pool. Implement /health to verify dependencies:

Java
GET /health

{
  "status": "ok",
  "checks": {
    "database": "ok",
    "redis": "ok",
    "disk_free_pct": 42
  }
}

On deploy, send SIGTERM, stop accepting new connections, finish in-flight requests, then exit — the LB stops routing within one health-check interval.

Sticky sessions

Stateless APIs avoid stickiness. Use it when:

  • In-memory session without Redis (legacy).
  • WebSocket connections tied to a specific server.

Prefer external session stores over stickiness — sticky routing breaks when instances scale down.

Java
# ALB sticky session cookie (avoid if possible)
Set-Cookie: AWSALB=...; Path=/; HttpOnly

TLS termination

StreamHub terminates TLS at the ALB. Traffic inside the VPC travels HTTP to app pods — acceptable with network isolation; some teams re-encrypt with mTLS via service mesh.

Java
# Client sees HTTPS; internal hop may be HTTP
curl -v https://api.streamhub.com/v1/feed
# * SSL connection using TLSv1.3

Scaling the load balancer itself

Managed LBs (ALB, Cloud LB) scale automatically. Self-hosted NGINX pairs use DNS round-robin or anycast VIPs. At extreme scale, DNS + multiple regional LBs + anycast IP distribute edge load globally.

Quick recall

Everything you need if you only revisit this box.

  • Load balancers spread traffic, terminate TLS, and remove unhealthy backends.
  • L7 balancers route by HTTP path/headers; L4 by IP and port.
  • Round-robin suits equal stateless servers; least-connections for variable work.
  • Health checks and graceful shutdown prevent dropped requests during deploys.
  • Avoid sticky sessions when Redis or JWT handles session state externally.
  • StreamHub added an ALB at ~20K DAU when one instance hit connection limits.

Test yourself

Answer these before moving on — recall is what makes it stick.