Load Balancer Types — L4 vs L7
debt(d7/e7/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). The wrong load balancer type choice manifests as subtle operational issues: unexpected latency, missing client IPs, failed WebSocket connections, or inability to route by path. No linter or SAST tool flags 'you picked L4 when you needed L7.' Detection requires load testing, production traffic analysis, or careful architecture review.
Closest to 'cross-cutting refactor across the codebase' (e7). Switching from L4 to L7 (or vice versa) mid-project typically requires: changing DNS/endpoints, reconfiguring TLS termination, updating backends to parse PROXY protocol or X-Forwarded-For headers, adjusting health checks, and potentially rearchitecting how services discover each other. It's not a one-line fix—it touches infrastructure-as-code, application config, and possibly application code.
Closest to 'strong gravitational pull' (b7). The load balancer tier choice shapes how you handle TLS, session affinity, routing, client IP preservation, and observability. Every new service must conform to the chosen pattern. The common_mistakes list shows the cascading effects: sticky sessions, PROXY protocol, re-encryption to backends—all are constrained by this architectural decision. Not quite b9 (you can change it with significant effort), but it definitely shapes every change.
Closest to 'notable trap' (t5). The misconception field explicitly states that developers assume 'L7 is strictly better than L4' when in fact L4 is the right choice for raw TCP workloads. This is a documented gotcha that experienced cloud architects learn, but it's not immediately obvious to developers new to load balancing. The assumption that 'higher layer = better' contradicts the reality that each tier serves different use cases.
Also Known As
TL;DR
Explanation
An L4 (transport-layer) load balancer operates at TCP/UDP: it sees source IP, destination IP, and ports, and forwards connections without inspecting their contents. This makes it fast, protocol-agnostic and cheap (AWS NLB, GCP TCP/UDP LB). An L7 (application-layer) load balancer terminates the application protocol — almost always HTTP(S) — so it can read URLs, headers, cookies and body content. That lets it do path-based routing, host-based routing, header-based A/B testing, sticky sessions by cookie, and request rewriting (AWS ALB, GCP HTTPS LB, Nginx, HAProxy in HTTP mode, Envoy). L7 is slower per packet and costs more, but unlocks the routing features modern microservices need. Service meshes add L7 sidecars on every pod, which is why a mesh's data plane needs careful tuning. Choosing between them is a question of: do you need protocol-aware routing, and can you afford to terminate TLS at the LB?
Common Misconception
Why It Matters
Common Mistakes
- Using an L7 load balancer for a raw TCP protocol — you either lose features or pay for routing you never use; prefer L4 for MySQL, Redis, gaming servers.
- Forgetting that L4 does not preserve the client IP by default — enable PROXY protocol and configure the backend to parse it.
- Terminating TLS at L7 without handling the re-encryption to the backend — internal traffic ends up in cleartext; set up an upstream TLS context or use the mesh.
- Relying on sticky-session cookies on an L4 LB — it cannot see cookies; use source-IP hashing or move to L7.
- Configuring both L4 and L7 in line without a plan — every additional hop is another timeout, retry and failure mode to debug.
Avoid When
- Mixing them without a clear boundary — if you need both, terminate L7 behind an L4 tier, not the other way around.
When To Use
- L7 — HTTP-based microservices needing path/host routing, sticky sessions by cookie, or centralised TLS termination.
- L4 — pure TCP/UDP workloads, very high throughput with minimal CPU, or preserving the exact client connection to the backend.