0

Load balancer — distributing incoming traffic across multiple app instances

Beginner5 min read·eng-18-006
interviewperformance

Concept

Load balancer — a component that distributes incoming requests across multiple servers (backends). When you have 3 app servers, the load balancer decides which server handles each request.

Why load balancers exist:

  • Horizontal scaling: Spread traffic across many servers.
  • High availability: If one server dies, the load balancer routes traffic to the remaining healthy ones.
  • Zero-downtime deployments: Deploy to servers one at a time, take them out of rotation, update, put back.

Load balancing algorithms:

  • Round-robin: Requests go to server 1, then 2, then 3, then 1 again. Simple and even.
  • Least connections: Routes to the server with the fewest active connections. Good when requests have variable processing time.
  • IP hash: Same client IP always goes to the same server ("sticky sessions"). Useful for stateful apps.
  • Weighted: Some servers get more traffic (e.g., larger servers get higher weight).

Layer 4 vs Layer 7:

  • L4 (TCP): Routes at the network level. Doesn't inspect HTTP content. Very fast.
  • L7 (HTTP): Routes based on HTTP — URL path, headers, host. Can route /api to one server and /static to another.

SSL termination: The load balancer handles HTTPS and forwards plain HTTP to backend servers. Backends don't need SSL certificates.

Health checks: Load balancers periodically ping backends (GET /health). If a server fails health checks, it's removed from rotation.

Tools: Nginx (common), HAProxy, AWS ALB/ELB, Caddy, Traefik (popular in Docker/K8s).

Code Example

nginx
# Nginx as a load balancer — nginx.conf
upstream app_servers {
    # Round-robin by default
    server app1:9000 weight=3;  # gets 3x traffic (bigger server)
    server app2:9000 weight=1;
    server app3:9000 weight=1;

    # Health check — remove server if it fails
    # (nginx-plus feature; use least_conn with open-source)
    least_conn;  # route to server with fewest connections
}

server {
    listen 80;
    listen 443 ssl;  # SSL termination here

    ssl_certificate     /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/key.pem;

    location / {
        proxy_pass http://app_servers;          # distribute to upstream
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
php
<?php
// TRUSTING THE LOAD BALANCER in Laravel
// When requests come through a load balancer, the real client IP is in X-Forwarded-For
// app/Http/Middleware/TrustProxies.php
class TrustProxies extends Middleware
{
    // Trust all proxies (or list specific IP ranges)
    protected $proxies = '*';

    protected $headers = Request::HEADER_X_FORWARDED_FOR
        | Request::HEADER_X_FORWARDED_HOST
        | Request::HEADER_X_FORWARDED_PORT
        | Request::HEADER_X_FORWARDED_PROTO;
}

// After configuring TrustProxies:
$request->ip();     // returns actual client IP, not load balancer IP
$request->secure(); // returns true if original request was HTTPS, even if LB forwards as HTTP

// HEALTH CHECK ENDPOINT — load balancer pings this
Route::get('/health', function () {
    // Check critical services
    DB::select('SELECT 1');
    Cache::put('health_check', true, 5);

    return response()->json(['status' => 'ok']);
});
// If this returns non-200, load balancer removes this server from rotation