TechCoder.io / DevOps

Load Balancers & Proxies

Learn about load balancing algorithms, reverse proxies, and Nginx configuration for scaling and securing web applications.

By TechCoder TeamLast updated: 2026-06-23
In a Nutshell

Learn about load balancing algorithms, reverse proxies, and Nginx configuration for scaling and securing web applications. This hands-on tutorial focuses on practical implementation of load balancers & proxies concepts.

Load Balancers & Proxies

Load balancers and reverse proxies are essential components for building scalable, highly available applications. They distribute traffic, improve performance, and enhance security.

What is a Load Balancer?

A load balancer distributes incoming network traffic across multiple backend servers to ensure no single server becomes a bottleneck.

                    +-----------------+
     User --------> |  Load Balancer  |
                    |    (Virtual)    |
                    +--------+--------+
                             |
          +------------------+------------------+
          |                  |                  |
     +----+----+        +----+----+        +----+----+
     | Server 1|        | Server 2|        | Server 3|
     | (App)   |        | (App)   |        | (App)   |
     +---------+        +---------+        +---------+

Types of Load Balancers

By OSI Layer

  1. Layer 4 (Transport Layer)

    • Works with TCP/UDP
    • Routes based on IP address and port
    • Faster, less intelligence
    • Examples: HAProxy (L4 mode), AWS NLB
  2. Layer 7 (Application Layer)

    • Works with HTTP/HTTPS
    • Can inspect content, headers, cookies
    • More intelligent routing
    • Examples: Nginx, HAProxy (L7 mode), AWS ALB

By Deployment

TypeDescriptionExamples
HardwarePhysical appliancesF5 BIG-IP, Citrix ADC
SoftwareInstalled on serversNginx, HAProxy, Traefik
CloudManaged servicesAWS ALB/NLB, Azure LB, GCP LB
DNSBased on DNS responsesRoute53, Cloudflare

Load Balancing Algorithms

Round Robin

Distributes requests sequentially to each server.

Request 1 -> Server 1
Request 2 -> Server 2
Request 3 -> Server 3
Request 4 -> Server 1 (cycles back)

Best for: Homogeneous servers with similar capacity.

Least Connections

Routes to the server with the fewest active connections.

Server 1: 50 connections -> Skip
Server 2: 20 connections <- Route here
Server 3: 35 connections -> Skip

Best for: Variable request processing times.

IP Hash

Routes based on client IP hash to ensure session persistence.

hash(client_ip) % server_count = server_index

Best for: Sessions requiring sticky connections.

Weighted Algorithms

Assign different weights to servers based on capacity.

Server 1: Weight 5 (handles 5x traffic)
Server 2: Weight 2
Server 3: Weight 1

Least Response Time

Routes to the server with lowest response time.

Best for: Optimizing user experience.

Health Checks

Load balancers monitor backend server health:

+-------------+     Health Check     +-------------+
|   Load      | <------- Ping ------- > |   Backend   |
|  Balancer   |    HTTP 200 Check    |   Server    |
|             | <------ /health ------ > |             |
+-------------+                      +-------------+

If unhealthy: Remove from pool If healthy again: Add back to pool

Health Check Types

  1. Ping (ICMP): Basic connectivity
  2. TCP Port: Check if port is open
  3. HTTP Check: Request specific endpoint
  4. Custom: Application-specific checks

Reverse Proxy vs Forward Proxy

Reverse Proxy

Client --> Reverse Proxy --> Backend Servers
              ^
         (Protects servers,
          load balances,
          caches content)
  • Hides backend servers
  • Load balancing
  • SSL termination
  • Caching
  • Compression

Forward Proxy

Client --> Forward Proxy --> Internet
              ^
         (Protects clients,
          filters content,
          anonymizes)
  • Protects clients
  • Content filtering
  • Access control
  • Anonymization

Nginx Basics

Nginx is a high-performance web server, reverse proxy, and load balancer.

Installation

# Ubuntu/Debian
sudo apt update
sudo apt install nginx

# RHEL/CentOS
sudo yum install nginx

# Docker
docker run -d -p 80:80 nginx

Basic Configuration

# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;
    
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    
    include /etc/nginx/conf.d/*.conf;
}

Static File Server

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.html index.htm;
    
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Cache static assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1M;
        add_header Cache-Control "public, immutable";
    }
}

Reverse Proxy Configuration

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        
        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;
        
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Load Balancer Configuration

# Upstream definition
upstream backend {
    least_conn;                    # Algorithm: least connections
    
    server 192.168.1.10:8080 weight=5;
    server 192.168.1.11:8080 weight=3;
    server 192.168.1.12:8080 backup;  # Backup server
    
    keepalive 32;                  # Keep connections open
}

server {
    listen 80;
    server_name app.example.com;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # Health check endpoint (nginx plus)
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

SSL/TLS Termination

server {
    listen 443 ssl http2;
    server_name secure.example.com;
    
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    
    # Modern SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    # Redirect HTTP to HTTPS
    location / {
        proxy_pass http://backend;
    }
}

# HTTP to HTTPS redirect
server {
    listen 80;
    server_name secure.example.com;
    return 301 https://$server_name$request_uri;
}

HAProxy Configuration

HAProxy is another popular load balancer known for performance and reliability.

# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0
    maxconn 4096
    user haproxy
    group haproxy

defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5000
    timeout client 50000
    timeout server 50000

# Stats page
listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats admin if TRUE

# Frontend
frontend web_frontend
    bind *:80
    default_backend web_servers

# Backend with health checks
backend web_servers
    balance roundrobin
    option httpchk GET /health
    
    server web1 192.168.1.10:8080 check
    server web2 192.168.1.11:8080 check
    server web3 192.168.1.12:8080 check backup

Cloud Load Balancers

AWS Application Load Balancer (ALB)

# Terraform example
resource "aws_lb" "app" {
  name               = "app-lb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.lb.id]
  subnets            = aws_subnet.public[*].id
}

resource "aws_lb_target_group" "app" {
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id
  
  health_check {
    path                = "/health"
    healthy_threshold   = 2
    unhealthy_threshold = 10
  }
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = aws_lb.app.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2016-08"
  certificate_arn   = aws_acm_certificate.cert.arn
  
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app.arn
  }
}

Key Features Comparison

FeatureNginxHAProxyAWS ALB
Layer 4
Layer 7
SSL Termination
WebSocket
Health Checks
Rate LimitingManual
WAF Integration
Auto ScalingManualManual

Common Use Cases

Microservices Routing

server {
    listen 80;
    server_name api.example.com;
    
    location /users/ {
        proxy_pass http://user-service;
    }
    
    location /orders/ {
        proxy_pass http://order-service;
    }
    
    location /inventory/ {
        proxy_pass http://inventory-service;
    }
}

A/B Testing

split_clients "${remote_addr}AAA" $variant {
    50%     backend_a;
    50%     backend_b;
}

server {
    location / {
        proxy_pass http://$variant;
    }
}

Blue-Green Deployment

upstream backend {
    server blue-server:8080;
    # server green-server:8080;  # Uncomment for green
}

Quiz

Quiz

Question 1 of 5

What is the main purpose of a load balancer?

To encrypt all network traffic
To distribute traffic across multiple servers
To store website backups
To develop web applications

Next Steps

With networking fundamentals covered, let's move on to version control: the foundation of modern software development workflows.