Topic Overview

Load Balancers (L4 vs L7)

Compare Layer 4 (transport) and Layer 7 (application) load balancers, their use cases, and when to use each type.

Load balancers distribute traffic across multiple servers. Layer 4 (L4) load balancers operate at the transport layer (TCP/UDP), while Layer 7 (L7) load balancers operate at the application layer (HTTP/HTTPS).


Layer 4 (L4) Load Balancer

Operates at: Transport Layer (TCP/UDP) Makes decisions based on: IP addresses and ports Does NOT inspect: Application data (HTTP headers, content)

How L4 Load Balancing Works

Client Request: TCP connection to 203.0.113.1:80
L4 Load Balancer: Sees only IP and port
  - Source IP: 192.168.1.100
  - Source Port: 5000
  - Dest IP: 203.0.113.1
  - Dest Port: 80
L4 Load Balancer: Routes based on algorithm
  - Round robin, least connections, etc.
Backend Server: Receives connection
  - Server 1, 2, or 3

Characteristics:

  • Fast: Minimal processing overhead
  • Simple: Only looks at IP and port
  • Transparent: Backend servers see original client IP
  • Protocol agnostic: Works with any TCP/UDP protocol

Layer 7 (L7) Load Balancer

Operates at: Application Layer (HTTP/HTTPS) Makes decisions based on: HTTP headers, URLs, cookies, content Inspects: Full HTTP request

How L7 Load Balancing Works

Client Request: HTTP GET /api/users
L7 Load Balancer: Inspects HTTP request
  - URL: /api/users
  - Host header: api.example.com
  - Cookie: session_id=abc123
  - Method: GET
L7 Load Balancer: Routes based on content
  - Route /api/users → user-service
  - Route /api/orders → order-service
  - Route based on session → sticky session
Backend Server: Receives HTTP request

Characteristics:

  • Intelligent routing: Can route based on URL, headers, content
  • SSL termination: Can terminate SSL/TLS
  • Content-based routing: Route different URLs to different services
  • More overhead: Inspects application data

Comparison

FeatureLayer 4 (L4)Layer 7 (L7)
LayerTransport (TCP/UDP)Application (HTTP/HTTPS)
Decision based onIP address, portURL, headers, cookies, content
PerformanceVery fast (low overhead)Slower (more processing)
Protocol supportAny TCP/UDPHTTP/HTTPS (primarily)
SSL terminationNoYes
Content inspectionNoYes
Sticky sessionsLimited (IP-based)Full (cookie-based)
Health checksTCP/UDP connectionHTTP status codes
Use caseHigh throughput, simple routingContent-based routing, SSL termination

Examples

L4 Load Balancer Configuration

# Nginx L4 Load Balancing (stream module)
stream {
    upstream backend {
        least_conn;  # Algorithm
        server 192.168.1.10:8080;
        server 192.168.1.11:8080;
        server 192.168.1.12:8080;
    }
    
    server {
        listen 80;
        proxy_pass backend;
        proxy_timeout 1s;
        proxy_responses 1;
    }
}

Characteristics:

  • Routes based on IP and port only
  • Fast, low latency
  • Works with any TCP/UDP protocol

L7 Load Balancer Configuration

# Nginx L7 Load Balancing (http module)
http {
    upstream user_service {
        least_conn;
        server 192.168.1.10:8080;
        server 192.168.1.11:8080;
    }
    
    upstream order_service {
        ip_hash;  # Sticky sessions
        server 192.168.1.20:8080;
        server 192.168.1.21:8080;
    }
    
    server {
        listen 80;
        
        # Route based on URL path
        location /api/users {
            proxy_pass http://user_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
        
        location /api/orders {
            proxy_pass http://order_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

Characteristics:

  • Routes based on URL path
  • Can set custom headers
  • Supports sticky sessions

L4 vs L7 Performance

# L4 Load Balancer (Simple, Fast)
class L4LoadBalancer:
    def route(self, packet):
        # Only look at IP and port
        src_ip, src_port = packet.get_source()
        dest_ip, dest_port = packet.get_destination()
        
        # Simple routing algorithm
        server = self.select_server(src_ip, src_port)
        return server.forward(packet)  # Fast, minimal processing

# L7 Load Balancer (Complex, Slower)
class L7LoadBalancer:
    def route(self, request):
        # Parse HTTP request
        method = request.get_method()
        url = request.get_url()
        headers = request.get_headers()
        cookies = request.get_cookies()
        
        # Complex routing logic
        if url.startswith('/api/users'):
            server = self.user_service_pool.select()
        elif url.startswith('/api/orders'):
            server = self.order_service_pool.select()
        elif 'session_id' in cookies:
            server = self.get_server_for_session(cookies['session_id'])
        else:
            server = self.default_pool.select()
        
        # Modify request (add headers, etc.)
        request.set_header('X-Real-IP', request.get_client_ip())
        
        return server.forward(request)  # More processing overhead

Use Cases

Use L4 Load Balancer When:

  • High throughput needed: Minimal processing overhead
  • Protocol agnostic: Need to balance non-HTTP traffic (database, custom protocols)
  • Simple routing: Route based on IP/port only
  • Low latency critical: Fast forwarding without inspection

Examples:

  • Database load balancing
  • Custom TCP/UDP protocols
  • High-performance web servers (simple routing)

Use L7 Load Balancer When:

  • Content-based routing: Route based on URL, headers
  • SSL termination: Terminate SSL at load balancer
  • Sticky sessions: Route same user to same server
  • Request/response modification: Add headers, modify content
  • API gateway functionality: Rate limiting, authentication

Examples:

  • Microservices routing (different URLs to different services)
  • Web applications (session affinity)
  • API gateways
  • CDN edge servers

Common Pitfalls

  • Using L7 for high throughput: L7 has more overhead. Fix: Use L4 for high throughput, L7 for content routing
  • Not understanding layer differences: Confusing L4 and L7 capabilities. Fix: Understand L4 = IP/port, L7 = HTTP content
  • SSL termination placement: Terminating SSL at L7 adds overhead. Fix: Consider SSL termination at L7 vs backend
  • Sticky sessions at L4: L4 can only do IP-based stickiness. Fix: Use L7 for cookie-based sticky sessions
  • Health check mismatch: L4 checks TCP connection, L7 checks HTTP. Fix: Use appropriate health checks
  • Performance expectations: Expecting L7 to be as fast as L4. Fix: L7 will always have more overhead

Interview Questions

Beginner

Q: What is the difference between Layer 4 and Layer 7 load balancers?

A:

Layer 4 (L4) Load Balancer:

  • Operates at: Transport layer (TCP/UDP)
  • Makes decisions based on: IP addresses and ports
  • Does NOT inspect: Application data (HTTP headers, content)
  • Performance: Very fast (minimal processing)
  • Use case: High throughput, simple routing

Layer 7 (L7) Load Balancer:

  • Operates at: Application layer (HTTP/HTTPS)
  • Makes decisions based on: URL, headers, cookies, content
  • Inspects: Full HTTP request
  • Performance: Slower (more processing overhead)
  • Use case: Content-based routing, SSL termination

Example:

L4: Routes based on IP:port only
  Client (192.168.1.100:5000) → Load Balancer → Server 1 or 2

L7: Routes based on HTTP content
  GET /api/users → user-service
  GET /api/orders → order-service

When to use:

  • L4: High throughput, protocol agnostic, simple routing
  • L7: Content-based routing, SSL termination, sticky sessions

Intermediate

Q: When would you choose L4 vs L7 load balancing? Explain with examples.

A:

Choose L4 When:

  1. High Throughput Required

    # Database load balancing
    # Need maximum performance, minimal overhead
    stream {
        upstream database {
            server db1:5432;
            server db2:5432;
        }
    }
    
  2. Non-HTTP Protocols

    # Custom TCP protocol
    # L4 works with any TCP/UDP protocol
    stream {
        upstream custom_service {
            server service1:9000;
            server service2:9000;
        }
    }
    
  3. Simple Routing

    # Just need to distribute load
    # No content-based routing needed
    upstream web_servers {
        server web1:80;
        server web2:80;
    }
    

Choose L7 When:

  1. Content-Based Routing

    # Route different URLs to different services
    location /api/users {
        proxy_pass http://user_service;
    }
    location /api/orders {
        proxy_pass http://order_service;
    }
    
  2. SSL Termination

    # Terminate SSL at load balancer
    server {
        listen 443 ssl;
        ssl_certificate /path/to/cert.pem;
        proxy_pass http://backend;
    }
    
  3. Sticky Sessions

    # Route same user to same server
    upstream backend {
        ip_hash;  # Or cookie-based
        server server1:80;
        server server2:80;
    }
    
  4. Request Modification

    # Add headers, modify requests
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    

Hybrid Approach:

  • Use L4 for high-throughput services
  • Use L7 for application-level routing
  • Combine both in architecture

Senior

Q: Design a load balancing architecture for a high-traffic web application that handles 1 million requests per second. How do you combine L4 and L7 load balancers, handle SSL termination, and ensure high availability?

A:

class HighTrafficLoadBalancer {
  private l4LoadBalancers: L4LoadBalancer[];
  private l7LoadBalancers: L7LoadBalancer[];
  private healthMonitor: HealthMonitor;
  private sslTerminator: SSLTerminator;
  
  constructor() {
    // L4 load balancers for high throughput
    this.l4LoadBalancers = [
      new L4LoadBalancer({ algorithm: 'least_connections' }),
      new L4LoadBalancer({ algorithm: 'least_connections' })
    ];
    
    // L7 load balancers for content routing
    this.l7LoadBalancers = [
      new L7LoadBalancer({ sslTermination: true }),
      new L7LoadBalancer({ sslTermination: true })
    ];
    
    this.healthMonitor = new HealthMonitor();
    this.sslTerminator = new SSLTerminator();
  }
  
  // Architecture: L4 → L7 → Backend
  async handleRequest(request: Request): Promise<Response> {
    // 1. L4 Load Balancer (First Layer)
    // High throughput, minimal processing
    const l4LB = this.selectL4LoadBalancer();
    
    // Route to L7 load balancer pool
    const l7LB = await l4LB.route(request, this.l7LoadBalancers);
    
    // 2. L7 Load Balancer (Second Layer)
    // Content-based routing, SSL termination
    if (request.isHTTPS()) {
      // SSL termination at L7
      request = await this.sslTerminator.terminate(request);
    }
    
    // Content-based routing
    const backend = await l7LB.route(request, {
      '/api/users': this.userServicePool,
      '/api/orders': this.orderServicePool,
      '/api/payments': this.paymentServicePool
    });
    
    // 3. Backend Service
    const response = await backend.handle(request);
    
    // 4. Response Processing
    return await l7LB.processResponse(response);
  }
  
  // L4 Load Balancer
  class L4LoadBalancer {
    async route(request: Request, targets: LoadBalancer[]): Promise<LoadBalancer> {
      // Simple routing based on IP/port
      // Fast, minimal overhead
      const target = this.selectTarget(targets, request.getSourceIP());
      return target;
    }
  }
  
  // L7 Load Balancer
  class L7LoadBalancer {
    async route(request: Request, routes: Map<string, ServicePool>): Promise<Service> {
      // Content-based routing
      const url = request.getURL();
      const path = this.extractPath(url);
      
      // Route based on URL path
      for (const [pattern, pool] of routes.entries()) {
        if (path.startsWith(pattern)) {
          return await pool.select(request);
        }
      }
      
      // Default route
      return await this.defaultPool.select(request);
    }
    
    async processResponse(response: Response): Promise<Response> {
      // Add headers, modify response
      response.setHeader('X-Load-Balancer', 'L7');
      return response;
    }
  }
  
  // SSL Termination
  class SSLTerminator {
    async terminate(request: HTTPSRequest): Promise<HTTPRequest> {
      // Decrypt SSL at load balancer
      // Reduces backend load
      const decrypted = await this.decrypt(request);
      return decrypted;
    }
  }
  
  // Health Monitoring
  class HealthMonitor {
    async checkHealth(): Promise<HealthStatus> {
      const checks = await Promise.all([
        this.checkL4Health(),
        this.checkL7Health(),
        this.checkBackendHealth()
      ]);
      
      return {
        l4: checks[0],
        l7: checks[1],
        backend: checks[2]
      };
    }
  }
}

Architecture:

Internet
L4 Load Balancers (High Throughput)
L7 Load Balancers (Content Routing, SSL Termination)
Backend Services (Application Servers)

Features:

  1. Two-tier architecture: L4 for throughput, L7 for routing
  2. SSL termination: At L7 to reduce backend load
  3. Content-based routing: L7 routes to appropriate services
  4. High availability: Multiple L4 and L7 load balancers
  5. Health monitoring: Monitor all layers
  6. Scalability: Scale each layer independently

Key Takeaways

  • L4 Load Balancer: Operates at transport layer (TCP/UDP), routes based on IP/port, fast, protocol agnostic
  • L7 Load Balancer: Operates at application layer (HTTP/HTTPS), routes based on content, slower, more features
  • Use L4 for: High throughput, non-HTTP protocols, simple routing
  • Use L7 for: Content-based routing, SSL termination, sticky sessions, request modification
  • Performance: L4 is faster (less overhead), L7 is slower (more processing)
  • Hybrid approach: Use L4 → L7 → Backend for high-traffic applications
  • Best practices: Use L4 for throughput, L7 for routing, terminate SSL at L7, monitor health

About the author

InterviewCrafted helps you master system design with patience. We believe in curiosity-led engineering, reflective writing, and designing systems that make future changes feel calm.