One-liner#

NLB is an L4 (TCP/UDP) load balancer; ALB is an L7 (HTTP/HTTPS) load balancer. NLB forwards packets as-is, while ALB parses HTTP requests before routing them.


How Each Layer Works#

NLB (L4):
  Client → [NLB: forward TCP packet] → Server
  - Does not inspect packet contents
  - Routes by IP + Port only

ALB (L7):
  Client → [ALB: parse HTTP request] → Server
  - Inspects Host header, URL path, HTTP method
  - Makes routing decisions based on request content

Key Differences#

NLBALB
OSI layerL4 (TCP/UDP)L7 (HTTP/HTTPS)
Routing basisIP + PortHost, Path, Header, Method
Latency~100µs (ultra-low)~1ms
Static IPYes (1 per AZ)No (DNS-based)
ThroughputMillions of requests/secTens of thousands of requests/sec
ProtocolsTCP, UDP, TLSHTTP, HTTPS, gRPC, WebSocket

Routing Capabilities#

NLB:
  - Port-based routing only
  - :443 → Target Group A
  - :8080 → Target Group B

ALB:
  - api.example.com/users → User service
  - api.example.com/orders → Order service
  - admin.example.com/* → Admin service
  - Header X-Version: v2 → V2 service

With ALB, a single load balancer can route to multiple services by Host or Path. With NLB, you’d have to split by port or deploy separate NLBs.


Performance#

NLB is significantly faster:

NLBALB
Latency~100µs~1ms (10× slower)
Warm-upNot requiredMay be needed under sudden traffic spikes
Connections/secMillionsTens of thousands

NLB simply forwards packets without inspecting them. ALB has overhead from HTTP parsing, header inspection, and routing rule evaluation.


Static IP#

NLB:
  AZ-a: 52.78.xxx.xxx (fixed)
  AZ-c: 13.125.xxx.xxx (fixed)
  → Great for IP allowlists

ALB:
  k8s-staging-xxxx.ap-northeast-2.elb.amazonaws.com
  → IP changes (DNS-based)
  → Cannot be IP-allowlisted; must use the domain

If a partner says “we need to whitelist your IP in our firewall,” you need NLB.


Security Group — The Deciding Factor for ALB#

Blocking direct access in a CloudFront → LB architecture#

The whole point of putting CloudFront in front is DDoS protection and WAF. If an attacker discovers the ALB endpoint and bypasses CloudFront, that protection is meaningless. This exact attack came up in a penetration test (H-10).

Normal flow:  User → CloudFront (WAF inspection) → ALB → Pod     ✅
Bypass attack: Attacker → ALB directly (WAF bypassed) → Pod      ❌ must block

To prevent this, the ALB must only accept traffic originating from CloudFront.

ALB: solved with Security Group + Prefix List#

CloudFront receives requests at edge locations worldwide and forwards them to the origin (ALB). AWS manages the IP ranges of those edge servers as a Managed Prefix List (pl-22a6434b) — roughly 45 IP ranges, automatically kept up to date.

ALB Security Group:
  Inbound rules:
    443 ← pl-22a6434b          (CloudFront edge IPs, ~45 ranges)
    443 ← 39.119.192.15/32     (Team member A)
    443 ← 124.49.102.36/32     (Team member B)
    443 ← 122.34.166.131/32    (Team member C)

Result:
  Requests from CloudFront edge       → Allowed ✅
  Direct access from team member IPs  → Allowed ✅
  Attacker hitting the ALB endpoint   → Blocked ❌ (IP not in SG)

Because ALB has full Security Group support, you can apply a Prefix List directly.

NLB: limited Security Group support#

NLB originally had no Security Group support at all. Support was added in 2023, but with constraints:

ConditionNLB SG support
Target type: IPSupported
Target type: InstanceNot supported
Target type: ALBNot supported
Adding SG to an existing NLBNot possible (only at creation)

In EKS environments, the AWS Load Balancer Controller often creates NLBs with Instance target type, which means you can’t attach a Security Group.

NLB (Instance targets):
  SG cannot be attached
  → Cannot apply the CloudFront Prefix List
  → Anyone can reach the NLB endpoint directly
  → The CloudFront + WAF security chain is effectively broken

Summary comparison#

NLBALB
SG supportAdded 2023, target type restrictionsFull support
Prefix ListConditional (IP targets only)Works out of the box
Block direct access bypassing CloudFrontDifficult or impossibleOne line with pl-22a6434b
ResultGap in security chainComplete security chain

This difference is the decisive reason ALB was chosen over NLB. No matter how good NLB’s ~100µs latency is, if you can’t build the CloudFront → WAF → SG security chain, it isn’t viable for a ticketing platform.


AWS Service Integrations#

ServiceNLBALB
CloudFront OriginRestrictedDirect connection
AWS WAF✗ (L4, no HTTP parsing)
ACM certificateManual managementAutomatic integration
Cognito auth

ALB is required to build the security chain (CloudFront → WAF → LB → backend).


Cost (ap-northeast-2)#

NLBALB
Hourly fixed$0.0225$0.0225
Processing unitNLCU $0.006LCU $0.008
Public IPStatic IP includedAuto-assigned $0.005/h/IP
Est. monthly (2 AZ)~$16~$23 (incl. IPs)

ALB is slightly more expensive, but the difference is not significant.


When to Use Each#

Use NLB when#

  • A static IP is required (partner allowlist)
  • Direct TCP/UDP handling (DB, messaging, game servers)
  • Ultra-low latency matters (real-time trading)
  • Exposing services via PrivateLink
  • Handling massive concurrent connections

Use ALB when#

  • Host/Path-based routing (multiple MSA services)
  • CloudFront + WAF security chain
  • HTTP redirects or fixed responses
  • gRPC routing (in front of Istio)
  • Cognito authentication integration

Real-world Experience#

In the PlayBall project, NLB was considered initially — L4 performance seemed advantageous for the burst of traffic at ticket sale opens.

However, once CloudFront was placed in front, we switched from NLB to ALB:

  1. CloudFront origin integration: ALB connects directly by DNS; NLB has restrictions
  2. Security Group: Applied the CloudFront Prefix List to the ALB SG to block direct access
  3. AWS WAF integration: WAF can only be attached directly to ALB
  4. Host-based routing: Multiple services (API, Grafana, ArgoCD) routed through a single ALB

The ~1ms latency of ALB was imperceptible in practice, thanks to CloudFront caching and Istio’s internal routing.