AWS Load Balancers: Complete Guide - Application, Network, Gateway, and Classic Load Balancers Comparison with Implementation

🎯 Introduction

AWS Load Balancers are critical components for building highly available, fault-tolerant, and scalable applications in the cloud. They distribute incoming traffic across multiple targets, ensuring optimal resource utilization and system reliability. This comprehensive guide explores all AWS Load Balancer types, their unique features, and when to use each one for maximum effectiveness.

Understanding the nuances between Application Load Balancer (ALB), Network Load Balancer (NLB), Gateway Load Balancer (GWLB), and Classic Load Balancer (CLB) is essential for architecting robust cloud solutions that can handle varying traffic patterns and requirements.

🔍 AWS Load Balancer Overview

📊 Load Balancer Types Comparison

graph TD
    A[AWS Load Balancers] --> B[Application Load Balancer<br/>ALB - Layer 7]
    A --> C[Network Load Balancer<br/>NLB - Layer 4]
    A --> D[Gateway Load Balancer<br/>GWLB - Layer 3]
    A --> E[Classic Load Balancer<br/>CLB - Layer 4/7]

    B --> F[HTTP/HTTPS<br/>Content-based routing<br/>Microservices<br/>Container workloads]
    C --> G[TCP/UDP<br/>Ultra-low latency<br/>High performance<br/>Static IP support]
    D --> H[Third-party appliances<br/>Firewalls<br/>Intrusion detection<br/>Security inspection]
    E --> I[Legacy applications<br/>Basic load balancing<br/>EC2-Classic<br/>Deprecated]

    style B fill:#4ecdc4
    style C fill:#ff6b6b
    style D fill:#feca57
    style E fill:#95a5a6

🏗️ High-Level Architecture

graph TD
    subgraph "Internet"
        Client[Client]
    end

    subgraph "AWS Load Balancers"
        ALB[Application LB<br/>Layer 7]
        NLB[Network LB<br/>Layer 4]
        GWLB[Gateway LB<br/>Layer 3]
    end

    subgraph "Target Groups"
        TG1[Web Servers<br/>EC2, ECS, Lambda]
        TG2[App Servers<br/>EC2, ECS]
        TG3[Security Appliances<br/>Third-party]
    end

    Client --> ALB
    Client --> NLB
    Client --> GWLB

    ALB --> TG1
    NLB --> TG2
    GWLB --> TG3

    style Client fill:#3498db
    style ALB fill:#2ecc71
    style NLB fill:#e74c3c
    style GWLB fill:#f39c12

🌐 Application Load Balancer (ALB)

📋 Overview and Features

Application Load Balancer operates at Layer 7 (Application Layer) and is ideal for HTTP/HTTPS traffic routing with advanced features for modern applications.

Key Features:

  • Content-based routing using URL paths, hostnames, headers, and query strings
  • HTTP/2 and WebSocket support
  • Native IPv6 support
  • Integration with AWS services (ECS, EKS, Lambda, etc.)
  • Advanced health checks
  • SSL/TLS termination and offloading
  • User authentication (OIDC, SAML)
  • Request tracing and detailed metrics

🛠️ ALB Implementation with Java

Maven Dependencies for ALB Management:

 1<dependencies>
 2    <!-- AWS SDK for ELB v2 -->
 3    <dependency>
 4        <groupId>software.amazon.awssdk</groupId>
 5        <artifactId>elasticloadbalancingv2</artifactId>
 6        <version>2.21.29</version>
 7    </dependency>
 8
 9    <!-- AWS SDK for EC2 (for target management) -->
10    <dependency>
11        <groupId>software.amazon.awssdk</groupId>
12        <artifactId>ec2</artifactId>
13        <version>2.21.29</version>
14    </dependency>
15
16    <!-- Spring Boot for application -->
17    <dependency>
18        <groupId>org.springframework.boot</groupId>
19        <artifactId>spring-boot-starter-web</artifactId>
20    </dependency>
21
22    <!-- Metrics and monitoring -->
23    <dependency>
24        <groupId>io.micrometer</groupId>
25        <artifactId>micrometer-registry-cloudwatch</artifactId>
26    </dependency>
27</dependencies>

🔧 ALB Configuration Service

  1@Service
  2@Slf4j
  3public class ApplicationLoadBalancerService {
  4
  5    private final ElasticLoadBalancingV2Client elbClient;
  6    private final Ec2Client ec2Client;
  7    private final String region;
  8    private final String accountId;
  9
 10    public ApplicationLoadBalancerService(@Value("${aws.region}") String region,
 11                                        @Value("${aws.account-id}") String accountId) {
 12        this.region = region;
 13        this.accountId = accountId;
 14        this.elbClient = ElasticLoadBalancingV2Client.builder()
 15            .region(Region.of(region))
 16            .build();
 17        this.ec2Client = Ec2Client.builder()
 18            .region(Region.of(region))
 19            .build();
 20    }
 21
 22    public String createApplicationLoadBalancer(ALBConfiguration config) {
 23        try {
 24            // 1. Create the load balancer
 25            CreateLoadBalancerRequest request = CreateLoadBalancerRequest.builder()
 26                .name(config.getName())
 27                .scheme(config.isInternetFacing() ? Scheme.INTERNET_FACING : Scheme.INTERNAL)
 28                .type(LoadBalancerTypeEnum.APPLICATION)
 29                .ipAddressType(config.getIpAddressType())
 30                .subnets(config.getSubnetIds())
 31                .securityGroups(config.getSecurityGroupIds())
 32                .tags(Tag.builder()
 33                    .key("Environment")
 34                    .value(config.getEnvironment())
 35                    .build(),
 36                    Tag.builder()
 37                    .key("Application")
 38                    .value(config.getApplicationName())
 39                    .build())
 40                .build();
 41
 42            CreateLoadBalancerResponse response = elbClient.createLoadBalancer(request);
 43            String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
 44
 45            log.info("Created Application Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
 46
 47            // 2. Create target group
 48            String targetGroupArn = createTargetGroup(config, loadBalancerArn);
 49
 50            // 3. Create listener
 51            createListener(loadBalancerArn, targetGroupArn, config);
 52
 53            // 4. Configure health checks
 54            configureHealthCheck(targetGroupArn, config.getHealthCheckConfig());
 55
 56            return loadBalancerArn;
 57
 58        } catch (Exception e) {
 59            log.error("Failed to create Application Load Balancer: {}", config.getName(), e);
 60            throw new RuntimeException("ALB creation failed", e);
 61        }
 62    }
 63
 64    private String createTargetGroup(ALBConfiguration config, String loadBalancerArn) {
 65        try {
 66            CreateTargetGroupRequest request = CreateTargetGroupRequest.builder()
 67                .name(config.getName() + "-tg")
 68                .protocol(ProtocolEnum.HTTP)
 69                .port(config.getTargetPort())
 70                .vpcId(config.getVpcId())
 71                .targetType(config.getTargetType())
 72                .healthCheckEnabled(true)
 73                .healthCheckPath(config.getHealthCheckConfig().getPath())
 74                .healthCheckProtocol(ProtocolEnum.HTTP)
 75                .healthCheckPort("traffic-port")
 76                .healthCheckIntervalSeconds(config.getHealthCheckConfig().getInterval())
 77                .healthyThresholdCount(config.getHealthCheckConfig().getHealthyThreshold())
 78                .unhealthyThresholdCount(config.getHealthCheckConfig().getUnhealthyThreshold())
 79                .healthCheckTimeoutSeconds(config.getHealthCheckConfig().getTimeout())
 80                .matcher(Matcher.builder()
 81                    .httpCode(config.getHealthCheckConfig().getSuccessCodes())
 82                    .build())
 83                .tags(Tag.builder()
 84                    .key("LoadBalancer")
 85                    .value(loadBalancerArn)
 86                    .build())
 87                .build();
 88
 89            CreateTargetGroupResponse response = elbClient.createTargetGroup(request);
 90            String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
 91
 92            log.info("Created target group: {} with ARN: {}", config.getName() + "-tg", targetGroupArn);
 93            return targetGroupArn;
 94
 95        } catch (Exception e) {
 96            log.error("Failed to create target group for ALB: {}", config.getName(), e);
 97            throw new RuntimeException("Target group creation failed", e);
 98        }
 99    }
100
101    private void createListener(String loadBalancerArn, String targetGroupArn, ALBConfiguration config) {
102        try {
103            CreateListenerRequest.Builder requestBuilder = CreateListenerRequest.builder()
104                .loadBalancerArn(loadBalancerArn)
105                .protocol(ProtocolEnum.HTTP)
106                .port(80)
107                .defaultActions(Action.builder()
108                    .type(ActionTypeEnum.FORWARD)
109                    .targetGroupArn(targetGroupArn)
110                    .build());
111
112            // Add HTTPS listener if SSL certificate is provided
113            if (config.getSslCertificateArn() != null) {
114                // Create HTTPS listener
115                CreateListenerRequest httpsRequest = CreateListenerRequest.builder()
116                    .loadBalancerArn(loadBalancerArn)
117                    .protocol(ProtocolEnum.HTTPS)
118                    .port(443)
119                    .certificates(Certificate.builder()
120                        .certificateArn(config.getSslCertificateArn())
121                        .build())
122                    .sslPolicy(config.getSslPolicy())
123                    .defaultActions(Action.builder()
124                        .type(ActionTypeEnum.FORWARD)
125                        .targetGroupArn(targetGroupArn)
126                        .build())
127                    .build();
128
129                elbClient.createListener(httpsRequest);
130
131                // Redirect HTTP to HTTPS
132                requestBuilder.defaultActions(Action.builder()
133                    .type(ActionTypeEnum.REDIRECT)
134                    .redirectConfig(RedirectActionConfig.builder()
135                        .protocol("HTTPS")
136                        .port("443")
137                        .statusCode(HttpRedirectActionStatusCodeEnum.HTTP_301)
138                        .build())
139                    .build());
140            }
141
142            elbClient.createListener(requestBuilder.build());
143            log.info("Created listeners for ALB: {}", loadBalancerArn);
144
145        } catch (Exception e) {
146            log.error("Failed to create listeners for ALB: {}", loadBalancerArn, e);
147            throw new RuntimeException("Listener creation failed", e);
148        }
149    }
150
151    public void registerTargets(String targetGroupArn, List<String> targetIds) {
152        try {
153            List<TargetDescription> targets = targetIds.stream()
154                .map(id -> TargetDescription.builder()
155                    .id(id)
156                    .build())
157                .collect(Collectors.toList());
158
159            RegisterTargetsRequest request = RegisterTargetsRequest.builder()
160                .targetGroupArn(targetGroupArn)
161                .targets(targets)
162                .build();
163
164            elbClient.registerTargets(request);
165            log.info("Registered {} targets to target group: {}", targetIds.size(), targetGroupArn);
166
167        } catch (Exception e) {
168            log.error("Failed to register targets to target group: {}", targetGroupArn, e);
169            throw new RuntimeException("Target registration failed", e);
170        }
171    }
172
173    public void createAdvancedRoutingRules(String listenerArn, List<RoutingRule> rules) {
174        try {
175            List<Rule> listenerRules = new ArrayList<>();
176            int priority = 100;
177
178            for (RoutingRule rule : rules) {
179                Rule listenerRule = Rule.builder()
180                    .priority(String.valueOf(priority++))
181                    .conditions(createRuleConditions(rule))
182                    .actions(createRuleActions(rule))
183                    .build();
184
185                listenerRules.add(listenerRule);
186            }
187
188            CreateRuleRequest request = CreateRuleRequest.builder()
189                .listenerArn(listenerArn)
190                .priority(String.valueOf(priority))
191                .conditions(listenerRules.get(0).conditions())
192                .actions(listenerRules.get(0).actions())
193                .build();
194
195            for (Rule rule : listenerRules) {
196                CreateRuleRequest ruleRequest = CreateRuleRequest.builder()
197                    .listenerArn(listenerArn)
198                    .priority(rule.priority())
199                    .conditions(rule.conditions())
200                    .actions(rule.actions())
201                    .build();
202
203                elbClient.createRule(ruleRequest);
204            }
205
206            log.info("Created {} advanced routing rules for listener: {}", rules.size(), listenerArn);
207
208        } catch (Exception e) {
209            log.error("Failed to create routing rules for listener: {}", listenerArn, e);
210            throw new RuntimeException("Rule creation failed", e);
211        }
212    }
213
214    private List<RuleCondition> createRuleConditions(RoutingRule rule) {
215        List<RuleCondition> conditions = new ArrayList<>();
216
217        if (rule.getPathPattern() != null) {
218            conditions.add(RuleCondition.builder()
219                .field("path-pattern")
220                .values(rule.getPathPattern())
221                .build());
222        }
223
224        if (rule.getHostHeader() != null) {
225            conditions.add(RuleCondition.builder()
226                .field("host-header")
227                .values(rule.getHostHeader())
228                .build());
229        }
230
231        if (rule.getHttpHeader() != null) {
232            conditions.add(RuleCondition.builder()
233                .field("http-header")
234                .httpHeaderConfig(HttpHeaderConditionConfig.builder()
235                    .httpHeaderName(rule.getHttpHeader().getKey())
236                    .values(rule.getHttpHeader().getValue())
237                    .build())
238                .build());
239        }
240
241        if (rule.getQueryString() != null) {
242            conditions.add(RuleCondition.builder()
243                .field("query-string")
244                .queryStringConfig(QueryStringConditionConfig.builder()
245                    .values(QueryStringKeyValuePair.builder()
246                        .key(rule.getQueryString().getKey())
247                        .value(rule.getQueryString().getValue())
248                        .build())
249                    .build())
250                .build());
251        }
252
253        return conditions;
254    }
255
256    private List<Action> createRuleActions(RoutingRule rule) {
257        List<Action> actions = new ArrayList<>();
258
259        switch (rule.getActionType()) {
260            case FORWARD:
261                actions.add(Action.builder()
262                    .type(ActionTypeEnum.FORWARD)
263                    .targetGroupArn(rule.getTargetGroupArn())
264                    .build());
265                break;
266
267            case REDIRECT:
268                actions.add(Action.builder()
269                    .type(ActionTypeEnum.REDIRECT)
270                    .redirectConfig(RedirectActionConfig.builder()
271                        .protocol(rule.getRedirectConfig().getProtocol())
272                        .host(rule.getRedirectConfig().getHost())
273                        .port(rule.getRedirectConfig().getPort())
274                        .path(rule.getRedirectConfig().getPath())
275                        .statusCode(HttpRedirectActionStatusCodeEnum.fromValue(rule.getRedirectConfig().getStatusCode()))
276                        .build())
277                    .build());
278                break;
279
280            case FIXED_RESPONSE:
281                actions.add(Action.builder()
282                    .type(ActionTypeEnum.FIXED_RESPONSE)
283                    .fixedResponseConfig(FixedResponseActionConfig.builder()
284                        .statusCode(rule.getFixedResponse().getStatusCode())
285                        .contentType(rule.getFixedResponse().getContentType())
286                        .messageBody(rule.getFixedResponse().getMessageBody())
287                        .build())
288                    .build());
289                break;
290
291            case WEIGHTED_FORWARD:
292                actions.add(Action.builder()
293                    .type(ActionTypeEnum.FORWARD)
294                    .forwardConfig(ForwardActionConfig.builder()
295                        .targetGroups(rule.getWeightedTargets().stream()
296                            .map(wt -> TargetGroupTuple.builder()
297                                .targetGroupArn(wt.getTargetGroupArn())
298                                .weight(wt.getWeight())
299                                .build())
300                            .collect(Collectors.toList()))
301                        .build())
302                    .build());
303                break;
304        }
305
306        return actions;
307    }
308
309    private void configureHealthCheck(String targetGroupArn, HealthCheckConfig healthConfig) {
310        try {
311            ModifyTargetGroupRequest request = ModifyTargetGroupRequest.builder()
312                .targetGroupArn(targetGroupArn)
313                .healthCheckEnabled(true)
314                .healthCheckPath(healthConfig.getPath())
315                .healthCheckIntervalSeconds(healthConfig.getInterval())
316                .healthCheckTimeoutSeconds(healthConfig.getTimeout())
317                .healthyThresholdCount(healthConfig.getHealthyThreshold())
318                .unhealthyThresholdCount(healthConfig.getUnhealthyThreshold())
319                .matcher(Matcher.builder()
320                    .httpCode(healthConfig.getSuccessCodes())
321                    .build())
322                .build();
323
324            elbClient.modifyTargetGroup(request);
325            log.info("Configured health check for target group: {}", targetGroupArn);
326
327        } catch (Exception e) {
328            log.error("Failed to configure health check for target group: {}", targetGroupArn, e);
329            throw new RuntimeException("Health check configuration failed", e);
330        }
331    }
332
333    // Supporting configuration classes
334    public static class ALBConfiguration {
335        private String name;
336        private boolean internetFacing;
337        private IpAddressType ipAddressType = IpAddressType.IPV4;
338        private List<String> subnetIds;
339        private List<String> securityGroupIds;
340        private String vpcId;
341        private String environment;
342        private String applicationName;
343        private int targetPort = 80;
344        private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
345        private String sslCertificateArn;
346        private String sslPolicy = "ELBSecurityPolicy-TLS-1-2-2017-01";
347        private HealthCheckConfig healthCheckConfig = new HealthCheckConfig();
348
349        // Constructors, getters, setters
350        public ALBConfiguration() {}
351
352        public ALBConfiguration(String name, List<String> subnetIds, List<String> securityGroupIds, String vpcId) {
353            this.name = name;
354            this.subnetIds = subnetIds;
355            this.securityGroupIds = securityGroupIds;
356            this.vpcId = vpcId;
357            this.internetFacing = true;
358            this.environment = "production";
359        }
360
361        // Getters and setters
362        public String getName() { return name; }
363        public void setName(String name) { this.name = name; }
364        public boolean isInternetFacing() { return internetFacing; }
365        public void setInternetFacing(boolean internetFacing) { this.internetFacing = internetFacing; }
366        public IpAddressType getIpAddressType() { return ipAddressType; }
367        public void setIpAddressType(IpAddressType ipAddressType) { this.ipAddressType = ipAddressType; }
368        public List<String> getSubnetIds() { return subnetIds; }
369        public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
370        public List<String> getSecurityGroupIds() { return securityGroupIds; }
371        public void setSecurityGroupIds(List<String> securityGroupIds) { this.securityGroupIds = securityGroupIds; }
372        public String getVpcId() { return vpcId; }
373        public void setVpcId(String vpcId) { this.vpcId = vpcId; }
374        public String getEnvironment() { return environment; }
375        public void setEnvironment(String environment) { this.environment = environment; }
376        public String getApplicationName() { return applicationName; }
377        public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
378        public int getTargetPort() { return targetPort; }
379        public void setTargetPort(int targetPort) { this.targetPort = targetPort; }
380        public TargetTypeEnum getTargetType() { return targetType; }
381        public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
382        public String getSslCertificateArn() { return sslCertificateArn; }
383        public void setSslCertificateArn(String sslCertificateArn) { this.sslCertificateArn = sslCertificateArn; }
384        public String getSslPolicy() { return sslPolicy; }
385        public void setSslPolicy(String sslPolicy) { this.sslPolicy = sslPolicy; }
386        public HealthCheckConfig getHealthCheckConfig() { return healthCheckConfig; }
387        public void setHealthCheckConfig(HealthCheckConfig healthCheckConfig) { this.healthCheckConfig = healthCheckConfig; }
388    }
389
390    public static class HealthCheckConfig {
391        private String path = "/health";
392        private int interval = 30;
393        private int timeout = 5;
394        private int healthyThreshold = 5;
395        private int unhealthyThreshold = 2;
396        private String successCodes = "200";
397
398        // Constructors, getters, setters
399        public HealthCheckConfig() {}
400
401        public String getPath() { return path; }
402        public void setPath(String path) { this.path = path; }
403        public int getInterval() { return interval; }
404        public void setInterval(int interval) { this.interval = interval; }
405        public int getTimeout() { return timeout; }
406        public void setTimeout(int timeout) { this.timeout = timeout; }
407        public int getHealthyThreshold() { return healthyThreshold; }
408        public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
409        public int getUnhealthyThreshold() { return unhealthyThreshold; }
410        public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
411        public String getSuccessCodes() { return successCodes; }
412        public void setSuccessCodes(String successCodes) { this.successCodes = successCodes; }
413    }
414
415    public static class RoutingRule {
416        private String pathPattern;
417        private String hostHeader;
418        private KeyValue httpHeader;
419        private KeyValue queryString;
420        private ActionType actionType;
421        private String targetGroupArn;
422        private RedirectConfig redirectConfig;
423        private FixedResponseConfig fixedResponse;
424        private List<WeightedTarget> weightedTargets;
425
426        public enum ActionType {
427            FORWARD, REDIRECT, FIXED_RESPONSE, WEIGHTED_FORWARD
428        }
429
430        // Constructors, getters, setters
431        public RoutingRule() {}
432
433        public String getPathPattern() { return pathPattern; }
434        public void setPathPattern(String pathPattern) { this.pathPattern = pathPattern; }
435        public String getHostHeader() { return hostHeader; }
436        public void setHostHeader(String hostHeader) { this.hostHeader = hostHeader; }
437        public KeyValue getHttpHeader() { return httpHeader; }
438        public void setHttpHeader(KeyValue httpHeader) { this.httpHeader = httpHeader; }
439        public KeyValue getQueryString() { return queryString; }
440        public void setQueryString(KeyValue queryString) { this.queryString = queryString; }
441        public ActionType getActionType() { return actionType; }
442        public void setActionType(ActionType actionType) { this.actionType = actionType; }
443        public String getTargetGroupArn() { return targetGroupArn; }
444        public void setTargetGroupArn(String targetGroupArn) { this.targetGroupArn = targetGroupArn; }
445        public RedirectConfig getRedirectConfig() { return redirectConfig; }
446        public void setRedirectConfig(RedirectConfig redirectConfig) { this.redirectConfig = redirectConfig; }
447        public FixedResponseConfig getFixedResponse() { return fixedResponse; }
448        public void setFixedResponse(FixedResponseConfig fixedResponse) { this.fixedResponse = fixedResponse; }
449        public List<WeightedTarget> getWeightedTargets() { return weightedTargets; }
450        public void setWeightedTargets(List<WeightedTarget> weightedTargets) { this.weightedTargets = weightedTargets; }
451    }
452
453    // Additional supporting classes...
454    public static class KeyValue {
455        private String key;
456        private String value;
457
458        public KeyValue() {}
459        public KeyValue(String key, String value) { this.key = key; this.value = value; }
460
461        public String getKey() { return key; }
462        public void setKey(String key) { this.key = key; }
463        public String getValue() { return value; }
464        public void setValue(String value) { this.value = value; }
465    }
466
467    public static class RedirectConfig {
468        private String protocol = "HTTPS";
469        private String host = "#{host}";
470        private String port = "443";
471        private String path = "/#{path}";
472        private String statusCode = "301";
473
474        // Constructors, getters, setters
475        public RedirectConfig() {}
476
477        public String getProtocol() { return protocol; }
478        public void setProtocol(String protocol) { this.protocol = protocol; }
479        public String getHost() { return host; }
480        public void setHost(String host) { this.host = host; }
481        public String getPort() { return port; }
482        public void setPort(String port) { this.port = port; }
483        public String getPath() { return path; }
484        public void setPath(String path) { this.path = path; }
485        public String getStatusCode() { return statusCode; }
486        public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
487    }
488
489    public static class FixedResponseConfig {
490        private String statusCode = "200";
491        private String contentType = "text/plain";
492        private String messageBody = "OK";
493
494        // Constructors, getters, setters
495        public FixedResponseConfig() {}
496
497        public String getStatusCode() { return statusCode; }
498        public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
499        public String getContentType() { return contentType; }
500        public void setContentType(String contentType) { this.contentType = contentType; }
501        public String getMessageBody() { return messageBody; }
502        public void setMessageBody(String messageBody) { this.messageBody = messageBody; }
503    }
504
505    public static class WeightedTarget {
506        private String targetGroupArn;
507        private Integer weight;
508
509        public WeightedTarget() {}
510        public WeightedTarget(String targetGroupArn, Integer weight) {
511            this.targetGroupArn = targetGroupArn;
512            this.weight = weight;
513        }
514
515        public String getTargetGroupArn() { return targetGroupArn; }
516        public void setTargetGroupArn(String targetGroupArn) { this.targetGroupArn = targetGroupArn; }
517        public Integer getWeight() { return weight; }
518        public void setWeight(Integer weight) { this.weight = weight; }
519    }
520}

🎯 ALB Use Cases

When to Use ALB:

  • Microservices architecture with path-based routing
  • Modern web applications requiring HTTP/2 support
  • Container workloads (ECS, EKS) with dynamic port mapping
  • Lambda functions as targets
  • Content-based routing based on headers, paths, or query strings
  • User authentication integration needed
  • WebSocket applications

When NOT to Use ALB:

  • Ultra-low latency requirements (use NLB instead)
  • Non-HTTP protocols (TCP, UDP)
  • Static IP address requirements
  • Simple load balancing with no advanced features needed

🚀 Network Load Balancer (NLB)

📋 Overview and Features

Network Load Balancer operates at Layer 4 (Transport Layer) and is designed for ultra-high performance and low latency applications.

Key Features:

  • Ultra-low latency (microsecond-level)
  • Handles millions of requests per second
  • Static IP addresses and Elastic IP support
  • Preserves source IP addresses
  • TCP, UDP, and TLS protocol support
  • Cross-zone load balancing available
  • Flow hash algorithm for connection affinity
  • Integration with PrivateLink

🛠️ NLB Implementation

  1@Service
  2@Slf4j
  3public class NetworkLoadBalancerService {
  4
  5    private final ElasticLoadBalancingV2Client elbClient;
  6    private final Ec2Client ec2Client;
  7
  8    public NetworkLoadBalancerService() {
  9        this.elbClient = ElasticLoadBalancingV2Client.builder().build();
 10        this.ec2Client = Ec2Client.builder().build();
 11    }
 12
 13    public String createNetworkLoadBalancer(NLBConfiguration config) {
 14        try {
 15            // 1. Allocate Elastic IPs if needed
 16            List<String> allocationIds = new ArrayList<>();
 17            if (config.isUseStaticIps()) {
 18                allocationIds = allocateElasticIPs(config.getSubnetIds().size());
 19            }
 20
 21            // 2. Create load balancer
 22            CreateLoadBalancerRequest.Builder requestBuilder = CreateLoadBalancerRequest.builder()
 23                .name(config.getName())
 24                .scheme(config.isInternetFacing() ? Scheme.INTERNET_FACING : Scheme.INTERNAL)
 25                .type(LoadBalancerTypeEnum.NETWORK)
 26                .ipAddressType(config.getIpAddressType());
 27
 28            // Configure subnets with static IPs if specified
 29            if (config.isUseStaticIps() && !allocationIds.isEmpty()) {
 30                List<SubnetMapping> subnetMappings = new ArrayList<>();
 31                for (int i = 0; i < config.getSubnetIds().size(); i++) {
 32                    subnetMappings.add(SubnetMapping.builder()
 33                        .subnetId(config.getSubnetIds().get(i))
 34                        .allocationId(i < allocationIds.size() ? allocationIds.get(i) : null)
 35                        .build());
 36                }
 37                requestBuilder.subnetMappings(subnetMappings);
 38            } else {
 39                requestBuilder.subnets(config.getSubnetIds());
 40            }
 41
 42            requestBuilder.tags(
 43                Tag.builder().key("Environment").value(config.getEnvironment()).build(),
 44                Tag.builder().key("Application").value(config.getApplicationName()).build(),
 45                Tag.builder().key("Type").value("NetworkLoadBalancer").build()
 46            );
 47
 48            CreateLoadBalancerResponse response = elbClient.createLoadBalancer(requestBuilder.build());
 49            String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
 50
 51            log.info("Created Network Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
 52
 53            // 3. Create target group
 54            String targetGroupArn = createNLBTargetGroup(config);
 55
 56            // 4. Create listener
 57            createNLBListener(loadBalancerArn, targetGroupArn, config);
 58
 59            return loadBalancerArn;
 60
 61        } catch (Exception e) {
 62            log.error("Failed to create Network Load Balancer: {}", config.getName(), e);
 63            throw new RuntimeException("NLB creation failed", e);
 64        }
 65    }
 66
 67    private List<String> allocateElasticIPs(int count) {
 68        List<String> allocationIds = new ArrayList<>();
 69
 70        for (int i = 0; i < count; i++) {
 71            try {
 72                AllocateAddressRequest request = AllocateAddressRequest.builder()
 73                    .domain(DomainType.VPC)
 74                    .build();
 75
 76                AllocateAddressResponse response = ec2Client.allocateAddress(request);
 77                allocationIds.add(response.allocationId());
 78
 79                log.info("Allocated Elastic IP: {} ({})", response.publicIp(), response.allocationId());
 80
 81            } catch (Exception e) {
 82                log.error("Failed to allocate Elastic IP", e);
 83                throw new RuntimeException("Elastic IP allocation failed", e);
 84            }
 85        }
 86
 87        return allocationIds;
 88    }
 89
 90    private String createNLBTargetGroup(NLBConfiguration config) {
 91        try {
 92            CreateTargetGroupRequest.Builder requestBuilder = CreateTargetGroupRequest.builder()
 93                .name(config.getName() + "-nlb-tg")
 94                .protocol(ProtocolEnum.fromValue(config.getProtocol().toUpperCase()))
 95                .port(config.getTargetPort())
 96                .vpcId(config.getVpcId())
 97                .targetType(config.getTargetType())
 98                .healthCheckEnabled(true)
 99                .healthCheckProtocol(ProtocolEnum.fromValue(config.getHealthCheckProtocol().toUpperCase()))
100                .healthCheckPort("traffic-port")
101                .healthCheckIntervalSeconds(config.getHealthCheckInterval())
102                .healthyThresholdCount(config.getHealthyThreshold())
103                .unhealthyThresholdCount(config.getUnhealthyThreshold());
104
105            // Configure health check path for HTTP/HTTPS
106            if (config.getHealthCheckProtocol().equalsIgnoreCase("HTTP") ||
107                config.getHealthCheckProtocol().equalsIgnoreCase("HTTPS")) {
108                requestBuilder.healthCheckPath(config.getHealthCheckPath());
109            }
110
111            // Configure deregistration delay
112            requestBuilder.targetGroupAttributes(
113                TargetGroupAttribute.builder()
114                    .key("deregistration_delay.timeout_seconds")
115                    .value(String.valueOf(config.getDeregistrationDelay()))
116                    .build(),
117                TargetGroupAttribute.builder()
118                    .key("preserve_client_ip.enabled")
119                    .value(String.valueOf(config.isPreserveClientIp()))
120                    .build(),
121                TargetGroupAttribute.builder()
122                    .key("proxy_protocol_v2.enabled")
123                    .value(String.valueOf(config.isProxyProtocolV2()))
124                    .build()
125            );
126
127            CreateTargetGroupResponse response = elbClient.createTargetGroup(requestBuilder.build());
128            String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
129
130            log.info("Created NLB target group: {} with ARN: {}", config.getName() + "-nlb-tg", targetGroupArn);
131            return targetGroupArn;
132
133        } catch (Exception e) {
134            log.error("Failed to create NLB target group for: {}", config.getName(), e);
135            throw new RuntimeException("NLB target group creation failed", e);
136        }
137    }
138
139    private void createNLBListener(String loadBalancerArn, String targetGroupArn, NLBConfiguration config) {
140        try {
141            CreateListenerRequest.Builder requestBuilder = CreateListenerRequest.builder()
142                .loadBalancerArn(loadBalancerArn)
143                .protocol(ProtocolEnum.fromValue(config.getProtocol().toUpperCase()))
144                .port(config.getListenerPort())
145                .defaultActions(Action.builder()
146                    .type(ActionTypeEnum.FORWARD)
147                    .targetGroupArn(targetGroupArn)
148                    .build());
149
150            // Add TLS configuration if needed
151            if (config.getProtocol().equalsIgnoreCase("TLS") && config.getSslCertificateArn() != null) {
152                requestBuilder.certificates(Certificate.builder()
153                    .certificateArn(config.getSslCertificateArn())
154                    .build());
155                requestBuilder.sslPolicy(config.getSslPolicy());
156            }
157
158            elbClient.createListener(requestBuilder.build());
159            log.info("Created NLB listener for port {} with protocol {}", config.getListenerPort(), config.getProtocol());
160
161        } catch (Exception e) {
162            log.error("Failed to create NLB listener for: {}", loadBalancerArn, e);
163            throw new RuntimeException("NLB listener creation failed", e);
164        }
165    }
166
167    public void enableCrossZoneLoadBalancing(String loadBalancerArn, boolean enabled) {
168        try {
169            ModifyLoadBalancerAttributesRequest request = ModifyLoadBalancerAttributesRequest.builder()
170                .loadBalancerArn(loadBalancerArn)
171                .attributes(LoadBalancerAttribute.builder()
172                    .key("load_balancing.cross_zone.enabled")
173                    .value(String.valueOf(enabled))
174                    .build())
175                .build();
176
177            elbClient.modifyLoadBalancerAttributes(request);
178            log.info("Cross-zone load balancing {} for NLB: {}",
179                enabled ? "enabled" : "disabled", loadBalancerArn);
180
181        } catch (Exception e) {
182            log.error("Failed to modify cross-zone load balancing for NLB: {}", loadBalancerArn, e);
183            throw new RuntimeException("Cross-zone configuration failed", e);
184        }
185    }
186
187    public void configureConnectionIdle(String loadBalancerArn, int idleTimeoutSeconds) {
188        try {
189            ModifyLoadBalancerAttributesRequest request = ModifyLoadBalancerAttributesRequest.builder()
190                .loadBalancerArn(loadBalancerArn)
191                .attributes(LoadBalancerAttribute.builder()
192                    .key("idle_timeout.timeout_seconds")
193                    .value(String.valueOf(idleTimeoutSeconds))
194                    .build())
195                .build();
196
197            elbClient.modifyLoadBalancerAttributes(request);
198            log.info("Configured idle timeout to {} seconds for NLB: {}", idleTimeoutSeconds, loadBalancerArn);
199
200        } catch (Exception e) {
201            log.error("Failed to configure idle timeout for NLB: {}", loadBalancerArn, e);
202            throw new RuntimeException("Idle timeout configuration failed", e);
203        }
204    }
205
206    // NLB Configuration class
207    public static class NLBConfiguration {
208        private String name;
209        private boolean internetFacing = true;
210        private IpAddressType ipAddressType = IpAddressType.IPV4;
211        private List<String> subnetIds;
212        private String vpcId;
213        private String environment = "production";
214        private String applicationName;
215        private String protocol = "TCP";
216        private int listenerPort = 80;
217        private int targetPort = 8080;
218        private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
219        private boolean useStaticIps = false;
220        private String healthCheckProtocol = "TCP";
221        private String healthCheckPath = "/";
222        private int healthCheckInterval = 30;
223        private int healthyThreshold = 3;
224        private int unhealthyThreshold = 3;
225        private int deregistrationDelay = 300;
226        private boolean preserveClientIp = false;
227        private boolean proxyProtocolV2 = false;
228        private String sslCertificateArn;
229        private String sslPolicy = "ELBSecurityPolicy-TLS-1-2-2017-01";
230
231        // Constructors, getters, setters
232        public NLBConfiguration() {}
233
234        public NLBConfiguration(String name, List<String> subnetIds, String vpcId) {
235            this.name = name;
236            this.subnetIds = subnetIds;
237            this.vpcId = vpcId;
238        }
239
240        // All getters and setters
241        public String getName() { return name; }
242        public void setName(String name) { this.name = name; }
243        public boolean isInternetFacing() { return internetFacing; }
244        public void setInternetFacing(boolean internetFacing) { this.internetFacing = internetFacing; }
245        public IpAddressType getIpAddressType() { return ipAddressType; }
246        public void setIpAddressType(IpAddressType ipAddressType) { this.ipAddressType = ipAddressType; }
247        public List<String> getSubnetIds() { return subnetIds; }
248        public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
249        public String getVpcId() { return vpcId; }
250        public void setVpcId(String vpcId) { this.vpcId = vpcId; }
251        public String getEnvironment() { return environment; }
252        public void setEnvironment(String environment) { this.environment = environment; }
253        public String getApplicationName() { return applicationName; }
254        public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
255        public String getProtocol() { return protocol; }
256        public void setProtocol(String protocol) { this.protocol = protocol; }
257        public int getListenerPort() { return listenerPort; }
258        public void setListenerPort(int listenerPort) { this.listenerPort = listenerPort; }
259        public int getTargetPort() { return targetPort; }
260        public void setTargetPort(int targetPort) { this.targetPort = targetPort; }
261        public TargetTypeEnum getTargetType() { return targetType; }
262        public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
263        public boolean isUseStaticIps() { return useStaticIps; }
264        public void setUseStaticIps(boolean useStaticIps) { this.useStaticIps = useStaticIps; }
265        public String getHealthCheckProtocol() { return healthCheckProtocol; }
266        public void setHealthCheckProtocol(String healthCheckProtocol) { this.healthCheckProtocol = healthCheckProtocol; }
267        public String getHealthCheckPath() { return healthCheckPath; }
268        public void setHealthCheckPath(String healthCheckPath) { this.healthCheckPath = healthCheckPath; }
269        public int getHealthCheckInterval() { return healthCheckInterval; }
270        public void setHealthCheckInterval(int healthCheckInterval) { this.healthCheckInterval = healthCheckInterval; }
271        public int getHealthyThreshold() { return healthyThreshold; }
272        public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
273        public int getUnhealthyThreshold() { return unhealthyThreshold; }
274        public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
275        public int getDeregistrationDelay() { return deregistrationDelay; }
276        public void setDeregistrationDelay(int deregistrationDelay) { this.deregistrationDelay = deregistrationDelay; }
277        public boolean isPreserveClientIp() { return preserveClientIp; }
278        public void setPreserveClientIp(boolean preserveClientIp) { this.preserveClientIp = preserveClientIp; }
279        public boolean isProxyProtocolV2() { return proxyProtocolV2; }
280        public void setProxyProtocolV2(boolean proxyProtocolV2) { this.proxyProtocolV2 = proxyProtocolV2; }
281        public String getSslCertificateArn() { return sslCertificateArn; }
282        public void setSslCertificateArn(String sslCertificateArn) { this.sslCertificateArn = sslCertificateArn; }
283        public String getSslPolicy() { return sslPolicy; }
284        public void setSslPolicy(String sslPolicy) { this.sslPolicy = sslPolicy; }
285    }
286}

🎯 NLB Use Cases

When to Use NLB:

  • Ultra-low latency applications
  • High-performance workloads (gaming, financial trading)
  • TCP/UDP protocols (databases, custom protocols)
  • Static IP addresses required
  • Source IP preservation needed
  • Extreme high throughput (millions of requests/second)
  • Long-running connections
  • PrivateLink integration

When NOT to Use NLB:

  • Content-based routing needed
  • HTTP/HTTPS-specific features required
  • WebSocket applications with advanced routing
  • Lambda function targets
  • User authentication integration needed

🛡️ Gateway Load Balancer (GWLB)

📋 Overview and Features

Gateway Load Balancer operates at Layer 3 (Network Layer) and is designed for deploying, scaling, and managing third-party network virtual appliances.

Key Features:

  • Third-party appliance integration (firewalls, intrusion detection)
  • Transparent network gateway
  • GENEVE protocol for traffic encapsulation
  • Scalable virtual appliance deployment
  • Source and destination IP preservation
  • Symmetric flow routing
  • Health checking for appliances

🛠️ GWLB Implementation

  1@Service
  2@Slf4j
  3public class GatewayLoadBalancerService {
  4
  5    private final ElasticLoadBalancingV2Client elbClient;
  6    private final Ec2Client ec2Client;
  7
  8    public GatewayLoadBalancerService() {
  9        this.elbClient = ElasticLoadBalancingV2Client.builder().build();
 10        this.ec2Client = Ec2Client.builder().build();
 11    }
 12
 13    public String createGatewayLoadBalancer(GWLBConfiguration config) {
 14        try {
 15            // 1. Create Gateway Load Balancer
 16            CreateLoadBalancerRequest request = CreateLoadBalancerRequest.builder()
 17                .name(config.getName())
 18                .type(LoadBalancerTypeEnum.GATEWAY)
 19                .subnets(config.getSubnetIds())
 20                .tags(
 21                    Tag.builder().key("Environment").value(config.getEnvironment()).build(),
 22                    Tag.builder().key("Application").value(config.getApplicationName()).build(),
 23                    Tag.builder().key("Type").value("GatewayLoadBalancer").build()
 24                )
 25                .build();
 26
 27            CreateLoadBalancerResponse response = elbClient.createLoadBalancer(request);
 28            String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
 29
 30            log.info("Created Gateway Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
 31
 32            // 2. Create target group for virtual appliances
 33            String targetGroupArn = createGWLBTargetGroup(config);
 34
 35            // 3. Create listener
 36            createGWLBListener(loadBalancerArn, targetGroupArn, config);
 37
 38            return loadBalancerArn;
 39
 40        } catch (Exception e) {
 41            log.error("Failed to create Gateway Load Balancer: {}", config.getName(), e);
 42            throw new RuntimeException("GWLB creation failed", e);
 43        }
 44    }
 45
 46    private String createGWLBTargetGroup(GWLBConfiguration config) {
 47        try {
 48            CreateTargetGroupRequest request = CreateTargetGroupRequest.builder()
 49                .name(config.getName() + "-gwlb-tg")
 50                .protocol(ProtocolEnum.GENEVE)
 51                .port(6081) // GENEVE default port
 52                .vpcId(config.getVpcId())
 53                .targetType(config.getTargetType())
 54                .healthCheckEnabled(true)
 55                .healthCheckProtocol(ProtocolEnum.fromValue(config.getHealthCheckProtocol().toUpperCase()))
 56                .healthCheckPort(String.valueOf(config.getHealthCheckPort()))
 57                .healthCheckIntervalSeconds(config.getHealthCheckInterval())
 58                .healthyThresholdCount(config.getHealthyThreshold())
 59                .unhealthyThresholdCount(config.getUnhealthyThreshold())
 60                .targetGroupAttributes(
 61                    TargetGroupAttribute.builder()
 62                        .key("deregistration_delay.timeout_seconds")
 63                        .value(String.valueOf(config.getDeregistrationDelay()))
 64                        .build()
 65                )
 66                .build();
 67
 68            CreateTargetGroupResponse response = elbClient.createTargetGroup(request);
 69            String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
 70
 71            log.info("Created GWLB target group: {} with ARN: {}", config.getName() + "-gwlb-tg", targetGroupArn);
 72            return targetGroupArn;
 73
 74        } catch (Exception e) {
 75            log.error("Failed to create GWLB target group for: {}", config.getName(), e);
 76            throw new RuntimeException("GWLB target group creation failed", e);
 77        }
 78    }
 79
 80    private void createGWLBListener(String loadBalancerArn, String targetGroupArn, GWLBConfiguration config) {
 81        try {
 82            CreateListenerRequest request = CreateListenerRequest.builder()
 83                .loadBalancerArn(loadBalancerArn)
 84                .defaultActions(Action.builder()
 85                    .type(ActionTypeEnum.FORWARD)
 86                    .targetGroupArn(targetGroupArn)
 87                    .build())
 88                .build();
 89
 90            elbClient.createListener(request);
 91            log.info("Created GWLB listener for: {}", loadBalancerArn);
 92
 93        } catch (Exception e) {
 94            log.error("Failed to create GWLB listener for: {}", loadBalancerArn, e);
 95            throw new RuntimeException("GWLB listener creation failed", e);
 96        }
 97    }
 98
 99    public void registerVirtualAppliances(String targetGroupArn, List<String> instanceIds) {
100        try {
101            List<TargetDescription> targets = instanceIds.stream()
102                .map(id -> TargetDescription.builder()
103                    .id(id)
104                    .build())
105                .collect(Collectors.toList());
106
107            RegisterTargetsRequest request = RegisterTargetsRequest.builder()
108                .targetGroupArn(targetGroupArn)
109                .targets(targets)
110                .build();
111
112            elbClient.registerTargets(request);
113            log.info("Registered {} virtual appliances to GWLB target group: {}", instanceIds.size(), targetGroupArn);
114
115        } catch (Exception e) {
116            log.error("Failed to register virtual appliances to target group: {}", targetGroupArn, e);
117            throw new RuntimeException("Virtual appliance registration failed", e);
118        }
119    }
120
121    // Create VPC Endpoint for GWLB service
122    public String createGWLBEndpoint(String gwlbArn, String vpcId, String subnetId, String routeTableId) {
123        try {
124            CreateVpcEndpointRequest request = CreateVpcEndpointRequest.builder()
125                .vpcId(vpcId)
126                .vpcEndpointType(VpcEndpointType.GATEWAY_LOAD_BALANCER)
127                .serviceName(extractServiceName(gwlbArn))
128                .subnetIds(subnetId)
129                .build();
130
131            CreateVpcEndpointResponse response = ec2Client.createVpcEndpoint(request);
132            String vpcEndpointId = response.vpcEndpoint().vpcEndpointId();
133
134            log.info("Created GWLB VPC Endpoint: {}", vpcEndpointId);
135
136            // Update route table to route traffic through GWLB endpoint
137            updateRouteTable(routeTableId, vpcEndpointId);
138
139            return vpcEndpointId;
140
141        } catch (Exception e) {
142            log.error("Failed to create GWLB VPC endpoint", e);
143            throw new RuntimeException("GWLB endpoint creation failed", e);
144        }
145    }
146
147    private String extractServiceName(String gwlbArn) {
148        // Extract service name from GWLB ARN for VPC endpoint
149        // Format: com.amazonaws.vpce.<region>.vpce-svc-<service-id>
150        String region = gwlbArn.split(":")[3];
151        String serviceId = gwlbArn.substring(gwlbArn.lastIndexOf("/") + 1);
152        return String.format("com.amazonaws.vpce.%s.vpce-svc-%s", region, serviceId);
153    }
154
155    private void updateRouteTable(String routeTableId, String vpcEndpointId) {
156        try {
157            CreateRouteRequest request = CreateRouteRequest.builder()
158                .routeTableId(routeTableId)
159                .destinationCidrBlock("0.0.0.0/0")
160                .vpcEndpointId(vpcEndpointId)
161                .build();
162
163            ec2Client.createRoute(request);
164            log.info("Updated route table {} to use GWLB endpoint: {}", routeTableId, vpcEndpointId);
165
166        } catch (Exception e) {
167            log.error("Failed to update route table: {}", routeTableId, e);
168            throw new RuntimeException("Route table update failed", e);
169        }
170    }
171
172    // GWLB Configuration class
173    public static class GWLBConfiguration {
174        private String name;
175        private List<String> subnetIds;
176        private String vpcId;
177        private String environment = "production";
178        private String applicationName;
179        private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
180        private String healthCheckProtocol = "TCP";
181        private int healthCheckPort = 80;
182        private int healthCheckInterval = 30;
183        private int healthyThreshold = 3;
184        private int unhealthyThreshold = 3;
185        private int deregistrationDelay = 300;
186
187        // Constructors, getters, setters
188        public GWLBConfiguration() {}
189
190        public GWLBConfiguration(String name, List<String> subnetIds, String vpcId) {
191            this.name = name;
192            this.subnetIds = subnetIds;
193            this.vpcId = vpcId;
194        }
195
196        // All getters and setters
197        public String getName() { return name; }
198        public void setName(String name) { this.name = name; }
199        public List<String> getSubnetIds() { return subnetIds; }
200        public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
201        public String getVpcId() { return vpcId; }
202        public void setVpcId(String vpcId) { this.vpcId = vpcId; }
203        public String getEnvironment() { return environment; }
204        public void setEnvironment(String environment) { this.environment = environment; }
205        public String getApplicationName() { return applicationName; }
206        public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
207        public TargetTypeEnum getTargetType() { return targetType; }
208        public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
209        public String getHealthCheckProtocol() { return healthCheckProtocol; }
210        public void setHealthCheckProtocol(String healthCheckProtocol) { this.healthCheckProtocol = healthCheckProtocol; }
211        public int getHealthCheckPort() { return healthCheckPort; }
212        public void setHealthCheckPort(int healthCheckPort) { this.healthCheckPort = healthCheckPort; }
213        public int getHealthCheckInterval() { return healthCheckInterval; }
214        public void setHealthCheckInterval(int healthCheckInterval) { this.healthCheckInterval = healthCheckInterval; }
215        public int getHealthyThreshold() { return healthyThreshold; }
216        public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
217        public int getUnhealthyThreshold() { return unhealthyThreshold; }
218        public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
219        public int getDeregistrationDelay() { return deregistrationDelay; }
220        public void setDeregistrationDelay(int deregistrationDelay) { this.deregistrationDelay = deregistrationDelay; }
221    }
222}

🎯 GWLB Use Cases

When to Use GWLB:

  • Third-party security appliances (firewalls, IDS/IPS)
  • Network function virtualization (NFV)
  • Deep packet inspection requirements
  • Transparent inline processing
  • Centralized security inspection
  • Compliance requirements for traffic inspection

When NOT to Use GWLB:

  • Basic load balancing needs
  • Application-layer routing
  • Direct application traffic distribution
  • Simple high availability setups

📊 Complete Load Balancer Comparison

🔍 Detailed Feature Matrix

FeatureALBNLBGWLBCLB
OSI LayerLayer 7 (Application)Layer 4 (Transport)Layer 3 (Network)Layer 4/7
ProtocolsHTTP, HTTPS, WebSocketTCP, UDP, TLSGENEVEHTTP, HTTPS, TCP, SSL
Target TypesInstance, IP, LambdaInstance, IP, ALBInstance, IPInstance
Static IP❌ No✅ Yes❌ No❌ No
Content Routing✅ Yes❌ No❌ No❌ Limited
WebSocket Support✅ Yes✅ Yes❌ No❌ No
HTTP/2 Support✅ Yes❌ No❌ No❌ No
Connection Draining✅ Yes✅ Yes✅ Yes✅ Yes
Cross-Zone LB✅ Always On⚠️ Optional❌ No⚠️ Optional
Health Check TypesHTTP, HTTPSTCP, HTTP, HTTPSTCP, HTTP, HTTPSTCP, HTTP, HTTPS
SSL Termination✅ Yes✅ Yes (TLS)❌ No✅ Yes
Source IP Preservation✅ Yes (headers)✅ Yes (native)✅ Yes❌ No
Integration with WAF✅ Yes❌ No❌ No❌ No
User Authentication✅ Yes❌ No❌ No❌ No
Request Tracing✅ Yes❌ Limited❌ No❌ Limited
Lambda Targets✅ Yes❌ No❌ No❌ No
Container Support✅ Excellent✅ Good✅ Good⚠️ Limited
Pricing ModelPer hour + LCUPer hour + NLCUPer hour + GLCUPer hour + data
PerformanceHighUltra-HighHighMedium
Latency~100ms~1ms~10ms~100ms

🎯 Use Case Decision Matrix

graph TD
    A[Choose Load Balancer] --> B{What's your primary use case?}

    B -->|Web Applications| C[Application Load Balancer]
    B -->|High Performance/Gaming| D[Network Load Balancer]
    B -->|Security Appliances| E[Gateway Load Balancer]
    B -->|Legacy Apps| F[Classic Load Balancer]

    C --> G{Advanced Routing Needed?}
    G -->|Yes| H[✅ Use ALB<br/>Content-based routing<br/>Microservices<br/>Containers]
    G -->|No| I{HTTP/2 or WebSocket?}
    I -->|Yes| H
    I -->|No| J[Consider NLB for performance]

    D --> K{Need Static IPs?}
    K -->|Yes| L[✅ Use NLB<br/>Static IP support<br/>Elastic IP integration]
    K -->|No| M{Ultra-low latency required?}
    M -->|Yes| L
    M -->|No| N[Consider ALB for features]

    E --> O[✅ Use GWLB<br/>Third-party appliances<br/>Security inspection<br/>NFV deployments]

    F --> P[❌ Migrate to ALB/NLB<br/>CLB is deprecated<br/>Limited features]

    style H fill:#2ecc71
    style L fill:#e74c3c
    style O fill:#f39c12
    style P fill:#95a5a6

📈 Monitoring and Health Checks

🔍 Load Balancer Monitoring Service

  1@Service
  2@Slf4j
  3public class LoadBalancerMonitoringService {
  4
  5    private final ElasticLoadBalancingV2Client elbClient;
  6    private final CloudWatchClient cloudWatchClient;
  7    private final MeterRegistry meterRegistry;
  8
  9    public LoadBalancerMonitoringService(MeterRegistry meterRegistry) {
 10        this.elbClient = ElasticLoadBalancingV2Client.builder().build();
 11        this.cloudWatchClient = CloudWatchClient.builder().build();
 12        this.meterRegistry = meterRegistry;
 13    }
 14
 15    @Scheduled(fixedRate = 60000) // Every minute
 16    public void collectLoadBalancerMetrics() {
 17        try {
 18            // Get all load balancers
 19            DescribeLoadBalancersResponse response = elbClient.describeLoadBalancers();
 20
 21            for (LoadBalancer lb : response.loadBalancers()) {
 22                collectMetricsForLoadBalancer(lb);
 23                collectTargetHealthMetrics(lb.loadBalancerArn());
 24            }
 25
 26        } catch (Exception e) {
 27            log.error("Failed to collect load balancer metrics", e);
 28        }
 29    }
 30
 31    private void collectMetricsForLoadBalancer(LoadBalancer lb) {
 32        String lbName = lb.loadBalancerName();
 33        LoadBalancerTypeEnum lbType = lb.type();
 34
 35        try {
 36            // Request Count
 37            collectCloudWatchMetric("RequestCount", lbName, lbType);
 38
 39            // Target Response Time
 40            collectCloudWatchMetric("TargetResponseTime", lbName, lbType);
 41
 42            // HTTP Error Codes
 43            if (lbType == LoadBalancerTypeEnum.APPLICATION) {
 44                collectCloudWatchMetric("HTTPCode_Target_2XX_Count", lbName, lbType);
 45                collectCloudWatchMetric("HTTPCode_Target_4XX_Count", lbName, lbType);
 46                collectCloudWatchMetric("HTTPCode_Target_5XX_Count", lbName, lbType);
 47                collectCloudWatchMetric("HTTPCode_ELB_4XX_Count", lbName, lbType);
 48                collectCloudWatchMetric("HTTPCode_ELB_5XX_Count", lbName, lbType);
 49            }
 50
 51            // Active Connection Count (for NLB)
 52            if (lbType == LoadBalancerTypeEnum.NETWORK) {
 53                collectCloudWatchMetric("ActiveFlowCount", lbName, lbType);
 54                collectCloudWatchMetric("NewFlowCount", lbName, lbType);
 55                collectCloudWatchMetric("ProcessedBytes", lbName, lbType);
 56            }
 57
 58        } catch (Exception e) {
 59            log.error("Failed to collect metrics for load balancer: {}", lbName, e);
 60        }
 61    }
 62
 63    private void collectCloudWatchMetric(String metricName, String lbName, LoadBalancerTypeEnum lbType) {
 64        try {
 65            String namespace = getNamespaceForLBType(lbType);
 66
 67            GetMetricStatisticsRequest request = GetMetricStatisticsRequest.builder()
 68                .namespace(namespace)
 69                .metricName(metricName)
 70                .dimensions(Dimension.builder()
 71                    .name("LoadBalancer")
 72                    .value(lbName)
 73                    .build())
 74                .startTime(Instant.now().minus(Duration.ofMinutes(5)))
 75                .endTime(Instant.now())
 76                .period(300) // 5 minutes
 77                .statistics(Statistic.AVERAGE, Statistic.SUM, Statistic.MAXIMUM)
 78                .build();
 79
 80            GetMetricStatisticsResponse response = cloudWatchClient.getMetricStatistics(request);
 81
 82            response.datapoints().forEach(datapoint -> {
 83                if (datapoint.average() != null) {
 84                    Gauge.builder("aws.loadbalancer." + metricName.toLowerCase() + ".average")
 85                        .tag("load_balancer", lbName)
 86                        .tag("type", lbType.toString())
 87                        .register(meterRegistry, () -> datapoint.average());
 88                }
 89
 90                if (datapoint.sum() != null) {
 91                    meterRegistry.counter("aws.loadbalancer." + metricName.toLowerCase() + ".total",
 92                        "load_balancer", lbName, "type", lbType.toString())
 93                        .increment(datapoint.sum());
 94                }
 95            });
 96
 97        } catch (Exception e) {
 98            log.error("Failed to collect CloudWatch metric {} for LB: {}", metricName, lbName, e);
 99        }
100    }
101
102    private void collectTargetHealthMetrics(String loadBalancerArn) {
103        try {
104            // Get target groups for this load balancer
105            DescribeTargetGroupsRequest request = DescribeTargetGroupsRequest.builder()
106                .loadBalancerArn(loadBalancerArn)
107                .build();
108
109            DescribeTargetGroupsResponse response = elbClient.describeTargetGroups(request);
110
111            for (TargetGroup tg : response.targetGroups()) {
112                collectTargetGroupHealthMetrics(tg);
113            }
114
115        } catch (Exception e) {
116            log.error("Failed to collect target health metrics for LB: {}", loadBalancerArn, e);
117        }
118    }
119
120    private void collectTargetGroupHealthMetrics(TargetGroup targetGroup) {
121        try {
122            DescribeTargetHealthRequest request = DescribeTargetHealthRequest.builder()
123                .targetGroupArn(targetGroup.targetGroupArn())
124                .build();
125
126            DescribeTargetHealthResponse response = elbClient.describeTargetHealth(request);
127
128            Map<String, Long> healthCounts = response.targetHealthDescriptions().stream()
129                .collect(Collectors.groupingBy(
130                    thd -> thd.targetHealth().state().toString(),
131                    Collectors.counting()
132                ));
133
134            String tgName = targetGroup.targetGroupName();
135
136            // Record target health metrics
137            healthCounts.forEach((state, count) ->
138                Gauge.builder("aws.loadbalancer.target.health")
139                    .tag("target_group", tgName)
140                    .tag("state", state)
141                    .register(meterRegistry, () -> count.doubleValue())
142            );
143
144            // Calculate health percentage
145            long totalTargets = response.targetHealthDescriptions().size();
146            long healthyTargets = healthCounts.getOrDefault("healthy", 0L);
147            double healthPercentage = totalTargets > 0 ? (double) healthyTargets / totalTargets * 100 : 0;
148
149            Gauge.builder("aws.loadbalancer.target.health_percentage")
150                .tag("target_group", tgName)
151                .register(meterRegistry, () -> healthPercentage);
152
153        } catch (Exception e) {
154            log.error("Failed to collect target group health metrics for: {}", targetGroup.targetGroupName(), e);
155        }
156    }
157
158    private String getNamespaceForLBType(LoadBalancerTypeEnum lbType) {
159        switch (lbType) {
160            case APPLICATION:
161                return "AWS/ApplicationELB";
162            case NETWORK:
163                return "AWS/NetworkELB";
164            case GATEWAY:
165                return "AWS/GatewayELB";
166            default:
167                return "AWS/ELB";
168        }
169    }
170
171    public LoadBalancerHealthSummary getHealthSummary(String loadBalancerArn) {
172        try {
173            // Get load balancer details
174            DescribeLoadBalancersRequest lbRequest = DescribeLoadBalancersRequest.builder()
175                .loadBalancerArns(loadBalancerArn)
176                .build();
177
178            DescribeLoadBalancersResponse lbResponse = elbClient.describeLoadBalancers(lbRequest);
179            LoadBalancer lb = lbResponse.loadBalancers().get(0);
180
181            // Get target groups
182            DescribeTargetGroupsRequest tgRequest = DescribeTargetGroupsRequest.builder()
183                .loadBalancerArn(loadBalancerArn)
184                .build();
185
186            DescribeTargetGroupsResponse tgResponse = elbClient.describeTargetGroups(tgRequest);
187
188            List<TargetGroupHealth> targetGroupHealths = new ArrayList<>();
189
190            for (TargetGroup tg : tgResponse.targetGroups()) {
191                DescribeTargetHealthRequest thRequest = DescribeTargetHealthRequest.builder()
192                    .targetGroupArn(tg.targetGroupArn())
193                    .build();
194
195                DescribeTargetHealthResponse thResponse = elbClient.describeTargetHealth(thRequest);
196
197                long totalTargets = thResponse.targetHealthDescriptions().size();
198                long healthyTargets = thResponse.targetHealthDescriptions().stream()
199                    .mapToLong(thd -> "healthy".equals(thd.targetHealth().state().toString()) ? 1 : 0)
200                    .sum();
201
202                targetGroupHealths.add(new TargetGroupHealth(
203                    tg.targetGroupName(),
204                    totalTargets,
205                    healthyTargets,
206                    totalTargets > 0 ? (double) healthyTargets / totalTargets * 100 : 0
207                ));
208            }
209
210            return new LoadBalancerHealthSummary(
211                lb.loadBalancerName(),
212                lb.type().toString(),
213                lb.state().code().toString(),
214                targetGroupHealths,
215                Instant.now()
216            );
217
218        } catch (Exception e) {
219            log.error("Failed to get health summary for LB: {}", loadBalancerArn, e);
220            return null;
221        }
222    }
223
224    // Supporting classes for health monitoring
225    public static class LoadBalancerHealthSummary {
226        private final String loadBalancerName;
227        private final String type;
228        private final String state;
229        private final List<TargetGroupHealth> targetGroups;
230        private final Instant timestamp;
231
232        public LoadBalancerHealthSummary(String loadBalancerName, String type, String state,
233                                       List<TargetGroupHealth> targetGroups, Instant timestamp) {
234            this.loadBalancerName = loadBalancerName;
235            this.type = type;
236            this.state = state;
237            this.targetGroups = targetGroups;
238            this.timestamp = timestamp;
239        }
240
241        // Getters
242        public String getLoadBalancerName() { return loadBalancerName; }
243        public String getType() { return type; }
244        public String getState() { return state; }
245        public List<TargetGroupHealth> getTargetGroups() { return targetGroups; }
246        public Instant getTimestamp() { return timestamp; }
247
248        public boolean isHealthy() {
249            return "active".equals(state) &&
250                   targetGroups.stream().allMatch(tg -> tg.getHealthPercentage() > 50);
251        }
252
253        @Override
254        public String toString() {
255            return String.format("LoadBalancerHealth{name='%s', type='%s', state='%s', healthy=%s, targetGroups=%d}",
256                loadBalancerName, type, state, isHealthy(), targetGroups.size());
257        }
258    }
259
260    public static class TargetGroupHealth {
261        private final String targetGroupName;
262        private final long totalTargets;
263        private final long healthyTargets;
264        private final double healthPercentage;
265
266        public TargetGroupHealth(String targetGroupName, long totalTargets, long healthyTargets, double healthPercentage) {
267            this.targetGroupName = targetGroupName;
268            this.totalTargets = totalTargets;
269            this.healthyTargets = healthyTargets;
270            this.healthPercentage = healthPercentage;
271        }
272
273        // Getters
274        public String getTargetGroupName() { return targetGroupName; }
275        public long getTotalTargets() { return totalTargets; }
276        public long getHealthyTargets() { return healthyTargets; }
277        public double getHealthPercentage() { return healthPercentage; }
278
279        @Override
280        public String toString() {
281            return String.format("TargetGroupHealth{name='%s', healthy=%d/%d (%.1f%%)}",
282                targetGroupName, healthyTargets, totalTargets, healthPercentage);
283        }
284    }
285}

🎯 Conclusion

AWS Load Balancers are essential components for building resilient, scalable, and high-performance applications in the cloud. Each type serves specific use cases and offers unique advantages:

🔑 Key Takeaways:

  1. Application Load Balancer (ALB): Best for modern web applications requiring advanced HTTP routing and features
  2. Network Load Balancer (NLB): Ideal for ultra-high performance, low latency, and TCP/UDP applications
  3. Gateway Load Balancer (GWLB): Perfect for third-party security appliances and network function virtualization
  4. Classic Load Balancer (CLB): Deprecated, migrate to ALB or NLB for better features and performance

📋 Selection Guidelines:

  1. For Web Applications: Start with ALB for HTTP/HTTPS traffic and advanced routing
  2. For High Performance: Choose NLB when latency and throughput are critical
  3. For Security Appliances: Use GWLB for transparent traffic inspection
  4. For Static IPs: NLB is the only option that supports static IP addresses
  5. For Containers/Lambda: ALB provides the best integration with modern compute services

🚀 Best Practices:

  1. Health Checks: Configure appropriate health checks for reliable traffic routing
  2. Monitoring: Implement comprehensive monitoring with CloudWatch and custom metrics
  3. Security: Use security groups, WAF integration, and SSL/TLS termination
  4. Cost Optimization: Choose the right load balancer type to avoid unnecessary costs
  5. High Availability: Deploy across multiple Availability Zones for fault tolerance

Understanding these differences enables you to architect robust, scalable, and cost-effective solutions that meet your specific application requirements and performance goals.