awesome-everything RU
↑ Back to the climb

Networking & Protocols

L4 vs L7 load balancing and client-IP preservation

Crux L4 routes on IP:port at 1–5 µs with 10–40 Gbps throughput; L7 parses HTTP at 100–500 µs for content routing — and X-Forwarded-For, RFC 7239, and PROXY protocol each preserve the client IP differently.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 11 min

Your service logs show every request coming from the same IP — the load balancer’s IP. You can’t rate-limit by client, can’t geo-block, can’t audit who did what. That is the price of not thinking carefully about which layer your load balancer operates at.

Layer 4: routing on IP and port

An L4 load balancer sees the TCP or UDP header only. It routes on the 4-tuple: source IP, source port, destination IP, destination port. It never reads the HTTP payload.

Mechanics:

  • Sees a TCP SYN from the client.
  • Picks a backend by the configured algorithm.
  • Either rewrites the destination IP (NAT mode) or opens a new TCP connection to the backend (proxy mode).
  • Forwards raw TCP segments in both directions.

Cost: ~1–5 µs per packet, <1% CPU. Throughput: 10–40 Gbps per server.

What L4 can do:

  • Route any TCP/UDP protocol (PostgreSQL, Redis, MQTT, custom binary).
  • Handle millions of connections per second.
  • Terminate TCP independently of HTTP.

What L4 cannot do:

  • Inspect or modify HTTP headers, path, or host.
  • Retry on HTTP 5xx errors (it does not understand HTTP).
  • Perform TLS termination without understanding the TLS record format.
  • Route different /api/v1/ and /api/v2/ paths to different backends.

Layer 7: routing on HTTP content

An L7 load balancer terminates the HTTP (and TLS) connection, parses the request, and applies routing rules before forwarding to a backend.

Mechanics:

  1. Terminates the client’s TLS — it sees the plaintext.
  2. Reads the HTTP method, path, Host header, custom headers.
  3. Applies routing rules (e.g., /api/ → pool A, /static/ → pool B).
  4. Opens a new connection (or reuses a pool) to the chosen backend.
  5. Forwards the request (adding proxy headers like X-Forwarded-For).

Cost: ~100–500 µs per request, 5–15% CPU. Throughput: 1–10 Gbps per server.

What L7 adds over L4:

  • Content-aware routing: path, hostname, header, cookie.
  • Retry on 5xx (understands HTTP semantics).
  • Per-endpoint metrics, rate limiting, auth checks.
  • TLS termination once at the LB edge instead of on every backend.
  • Traffic splitting (10% → canary, 90% → stable).
L4 vs L7 load balancing
L4 hop latency
1–5 µs
L7 hop latency
100–500 µs
L4 throughput per server
10–40 Gbps
L7 throughput per server
1–10 Gbps
L4 CPU per packet
&lt;1%
L7 CPU per request
5–15%
L4 protocols
any TCP/UDP
L7 protocols
HTTP, gRPC, WebSocket

Client-IP preservation

When the LB forwards a request to the backend, the backend sees the LB’s IP as the TCP source address — not the real client. Three standards exist to restore this:

X-Forwarded-For (XFF)

X-Forwarded-For: 203.0.113.195

The LB appends the client IP to this header. HTTP-only. Trivially spoofed: a malicious client can send X-Forwarded-For: 1.2.3.4 and an unvalidated proxy appends rather than overwrites. Only the rightmost IP added by a trusted proxy is reliable.

RFC 7239 Forwarded header

Forwarded: for=203.0.113.195;proto=https;host=example.com

Standardized (RFC 7239), structured format, harder to parse incorrectly. Includes protocol and host alongside the IP. Still HTTP-only but less prone to accidental misparse.

PROXY protocol (HAProxy)

A text or binary header prepended before the TLS/HTTP payload:

PROXY TCP4 203.0.113.195 93.184.216.34 35646 80\r\n

Works for any TCP/UDP protocol — no HTTP required. The backend TCP stack reads the header before any application-layer parsing. Harder to spoof than an HTTP header because it is inserted at the transport layer by a trusted proxy. Nginx, HAProxy, and Envoy all support PROXY protocol.

Which to choose: HTTP services behind trusted proxies → XFF or RFC 7239. Non-HTTP services (PostgreSQL, MQTT, custom binary) or where strict tamper-resistance matters → PROXY protocol.

Trace it
1/4

Trace a request that switches from L4 to L7 as it moves through a two-tier LB architecture.

1
Step 1 of 4
A client connects to an L4 load balancer on port 443. What does the L4 LB see, and what can it route on?
2
Locked
The L4 LB forwards to an L7 LB (e.g., an Envoy instance). The L7 LB terminates TLS. What does it see now?
3
Locked
The L7 LB adds X-Forwarded-For and forwards to backend pool A. The backend reads XFF. What trust assumption must it make?
4
Locked
A backend needs the real client IP for rate limiting but is a raw TCP service (not HTTP). How does it get the client IP?
Which RFC?

Which RFC standardizes the Forwarded header for preserving client IP through proxies?

Why this works

Why L4 + L7 in series? Many production architectures use an L4 LB at the network edge (BGP anycast, absorbs floods, handles millions of connections) and an L7 LB behind it (terminates TLS, applies routing policies, emits per-endpoint metrics). The L4 layer handles the raw packet pressure cheaply; the L7 layer adds intelligence without needing to scale to packet-rate throughput. AWS uses this two-tier pattern: Network Load Balancer (L4) → Application Load Balancer (L7).

Quiz

You need to route /api/payments/ to a PCI-DSS-compliant backend pool and /api/catalog/ to a regular pool. Which load balancer layer can do this, and why?

Recall before you leave
  1. 01
    You want to route by HTTP path and retry on 5xx. Which LB layer is required, and what is its latency cost?
  2. 02
    Why is X-Forwarded-For spoofable, and how does PROXY protocol improve on it?
  3. 03
    When would you choose L4 over L7 even for HTTP traffic?
Recap

L4 load balancers route on the TCP/UDP 4-tuple — they are fast (1–5 µs, 10–40 Gbps) and protocol-agnostic but cannot inspect HTTP. L7 load balancers terminate TLS, parse HTTP, and enable path/host/header routing and 5xx retries — at the cost of 100–500 µs latency and 5–15% CPU. Both types hide the client’s IP from the backend; the three standards to restore it are X-Forwarded-For (de facto but spoofable), RFC 7239 Forwarded (structured, HTTP-only), and PROXY protocol (binary, any TCP/UDP, hardest to spoof). Production architectures often stack L4 at the edge and L7 behind it: raw packet throughput handled cheaply at L4, content intelligence at L7.

Connected lessons
appears again in162
Continue the climb ↑Health checks, connection draining, and slow start
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.