← Tutorials
⚖️ AWS

ALB vs NLB on AWS: choose and test the request path

Choose ALB, NLB or both from your routing, TLS and address requirements. Check client IPs, health checks and failure behavior before cutover.

By The Downtime · Jul 6, 2026 · 1:31 PM ·Updated 1 week ago
ALB vs NLB on AWS: choose and test the request path

Use an Application Load Balancer (ALB) when your service needs HTTP request routing or AWS WAF. Use a Network Load Balancer (NLB) when the transport protocol, a fixed address requirement or a PrivateLink endpoint service calls for it. Some applications need both.

Choose against the whole request path. A fixed IP requirement does not remove your need for HTTP routing, and a faster load balancer cannot repair a slow database. This guide walks through that choice, the settings that change its behavior, and a staging test before cutover.

Start with the request you need to route

An ALB can choose a target group from the request's hostname, path, headers or other HTTP fields. For example, api.example.com/orders/* can go to an orders service while another path goes to a separate service. The backend groups can have different health checks. AWS documents the supported listener conditions.

Its listeners use HTTP or HTTPS. HTTPS listeners support HTTP/2; WebSocket upgrades are supported too, subject to the documented target-group restrictions. For gRPC, configure the target group's protocol version as gRPC and use an HTTPS listener. Merely selecting HTTPS does not configure the backend protocol. See the ALB listener guide and target-group protocol versions.

An NLB handles transport connections and flows. Its listener protocol list now includes TCP, TLS, UDP, TCP_UDP, QUIC and TCP_QUIC. QUIC listeners pass traffic through to QUIC-capable backends. They do not turn the NLB into an HTTP path router. Check the current NLB listener documentation against the protocol your clients use.

Use this table to identify the requirement that drives your design. If two rows apply, satisfy both before choosing.

Requirement Starting point
Route by hostname or URL path ALB listener rules
Apply AWS WAF at the load balancer ALB in an AWS Region
Carry a custom TCP or UDP service NLB with matching listener and target protocol
Let the application terminate the original TLS connection NLB TCP listener
Combine fixed addresses or PrivateLink with HTTP routing NLB with an ALB target

AWS WAF supports ALB as a regional resource; NLB is not a direct web ACL attachment point. A WAF requirement therefore belongs in the ALB column. AWS WAF supported resources.

Decide where TLS ends

With an ALB HTTPS listener, the client TLS connection ends at the ALB. An HTTPS target group creates another encrypted connection to the backend. AWS says ALB does not validate the target's certificate. Record that distinction if your security requirement includes backend certificate identity checks. ALB target-group routing.

For NLB, a TLS listener terminates TLS at the load balancer. A TCP listener on port 443 passes the encrypted connection to the target, which holds the certificate and performs the handshake. Choose TCP passthrough when the application must receive the original TLS session. The listener name matters: selecting TLS is an explicit termination choice. NLB secure listeners.

Test a client handshake through the intended hostname. Check the certificate presented, protocol negotiation and application response. A successful TCP connection alone leaves all three untested.

Fixed addresses and HTTP routing can coexist

An NLB has a static IP for each enabled Availability Zone. An internet-facing NLB can use an Elastic IP for each zone. Keep the full address set in any allowlist; pinning clients to one zonal address creates a dependency on that zone. DNS answers and zonal health still matter. AWS static addresses and request routing.

When a service needs those addresses and HTTP routing, AWS supports an ALB as an NLB target. The two load balancers must be in the same account and VPC. The NLB target group uses type alb and protocol TCP, with its port matching an ALB listener. This configuration can also back a PrivateLink endpoint service. AWS setup guide.

For a hypothetical HTTPS API, the path is: client, NLB TCP listener on 443, ALB HTTPS listener on 443, then the application target group. TLS ends at the ALB. Its rules choose the service. The NLB's HTTP or HTTPS health check must reach a matching ALB listener and a path the ALB forwards correctly. Test that health-check request separately from the normal hostname-based request.

Adding another load balancer adds configuration to operate. Use this arrangement when its requirements justify it; a single ALB is enough for many web applications.

Verify the client address your application receives

ALB uses X-Forwarded-For to convey the client address. Its default mode appends the address to an existing header, so a request can contain a chain of addresses. Configure the application's trusted proxies and verify the value it logs. Do not accept an arbitrary client-supplied header entry as an authorization identity. ALB forwarded-header behavior.

NLB client-IP preservation depends on the target type, protocol and network path. It is enabled by default for instance targets. For IP targets using TCP or TLS, it is disabled by default. PrivateLink traffic still appears with an NLB private source address. Address-family translation and intermediate network appliances introduce further limits. NLB target-group attributes.

During a staging request, compare the known client address with the backend socket address and application log. Repeat through each supported entry path. If you use Proxy Protocol v2, confirm the server parses it before enabling it; those extra bytes are part of the connection your server receives.

Health checks have failure behavior of their own

NLB supports TCP, HTTP and HTTPS health checks. Its HTTP checks can use a path and status-code matcher; the default successful range is 200-399. For a UDP or QUIC service, make the separate health endpoint reflect that service's readiness. An unrelated web server returning 200 proves little about the transport service. NLB health checks.

ALB HTTP health checks default to status 200 and also support configured matchers. Neither product's status-code matcher asserts that a response body contains the expected application result. Use a separate application check for that. ALB health checks.

Both products can fail open when all registered targets fail their health checks, sending traffic to unhealthy targets. Treat this as an explicit test case. An unhealthy status is not an access-control rule. Our readiness and deep-check guide explains how to separate routing decisions from application validation.

Cross-zone settings also affect the result. ALB enables cross-zone balancing at the load-balancer level, with a target-group override available. NLB disables it by default. Inspect the effective settings and the capacity available in each zone before relying on surviving targets. AWS cross-zone behavior.

Run a bounded staging test before cutover

Use an isolated environment with synthetic data, a named operator and an agreed stop condition. Keep its configuration close enough to production to exercise the same listeners and target types. The worksheet below describes tests to run; it does not report measured results.

Test Evidence to keep
Send requests to each hostname and path Expected service and response body, including the default route
Open a fresh TLS connection Presented certificate, negotiated protocol and termination point
Send from a known client Socket source and application-reported client address
Make one target fail readiness Target state, new-request errors and existing-connection behavior
Make every target fail readiness Whether traffic continues and how the application responds
Restore readiness Target recovery, successful application requests and error rate

Change one failure condition at a time. Keep one long-lived connection open while sending fresh requests so the test captures both behaviors. Record timestamps from the client and target logs; do not turn the health-check interval into a promised recovery time.

Measure latency using your request sizes, TLS setup and connection reuse pattern. Keep the offered load and backend capacity comparable, and include errors in the result. This article makes no microsecond or millisecond performance promise. A load test and the multi-AZ capacity drill provide evidence for the workload you intend to run.

After cutover, keep an external check on the public hostname and an application response you recognize. Use Pingy to check that separate path for failures a target health check can miss, including DNS and client-facing TLS problems. Compare it with load-balancer metrics and backend logs when an alert fires.

💬 Comments (0)

No comments yet — be the first to weigh in.

Join the conversation.