# Elastic Load Balancing (ELB)

Source: /aws/services/elb/

## Introduction

Elastic Load Balancing (ELB) is a service that allows users to distribute incoming traffic across multiple targets, such as EC2 instances, containers, IP addresses, and lambda functions and automatically scales its request handling capacity in response to incoming traffic.
It also monitors the health of its registered targets and ensures that it routes traffic only to healthy targets.
You can check [the official AWS documentation](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/what-is-load-balancing.html) to understand the basic terms and concepts used in the ELB.

Localstack allows you to use the Elastic Load Balancing APIs in your local environment to create, edit, and view load balancers, target groups, listeners, and rules.
The supported APIs are available on the API coverage section for [ELBv1](#api-coverage-elbv1) and [ELBv2](#api-coverage-elbv2), which provides information on the extent of ELB's integration with LocalStack.

## Getting started

This guide is designed for users new to Elastic Load Balancing and assumes basic knowledge of the AWS CLI and our [`lstk aws`](/aws/developer-tools/running-localstack/lstk/cloud-and-iac-commands/#aws) command.

Start your LocalStack container using your preferred method.
We will demonstrate how to create an Application Load Balancer, along with its target group, listener, and rule, and forward requests to an IP target.

### Start a target server

Launch an HTTP server which will serve as the target for our load balancer.

```bash
docker run --rm -itd -p 5678:80 ealen/echo-server
```

### Create a load balancer

To specify the subnet and VPC in which the load balancer will be created, you can use the [`DescribeSubnets`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_DescribeSubnets.html) API to retrieve the subnet ID and VPC ID.
In this example, we will use the subnet and VPC in the `us-east-1f` availability zone.

```bash
subnet_info=$(lstk aws ec2 describe-subnets --filters Name=availability-zone,Values=us-east-1f \
    | jq -r '.Subnets[] | select(.AvailabilityZone == "us-east-1f") | {SubnetId: .SubnetId, VpcId: .VpcId}')

subnet_id=$(echo $subnet_info | jq -r '.SubnetId')

vpc_id=$(echo $subnet_info | jq -r '.VpcId')
```

To create a load balancer, you can use the [`CreateLoadBalancer`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateLoadBalancer.html) API.
The following command creates an Application Load Balancer named `example-lb`:

```bash
loadBalancer=$(lstk aws elbv2 create-load-balancer --name example-lb \
    --subnets $subnet_id | jq -r '.LoadBalancers[]|.LoadBalancerArn')
```

### Create a target group

To create a target group, you can use the [`CreateTargetGroup`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateTargetGroup.html) API.
The following command creates a target group named `example-target-group`:

```bash
targetGroup=$(lstk aws elbv2 create-target-group --name example-target-group \
    --protocol HTTP --target-type ip --port 80 --vpc-id $vpc_id \
    | jq -r '.TargetGroups[].TargetGroupArn')
```

### Register a target

To register a target, you can use the [`RegisterTargets`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_RegisterTargets.html) API.
The following command registers the target with the target group created in the previous step:

```bash
lstk aws elbv2 register-targets --targets Id=127.0.0.1,Port=5678,AvailabilityZone=all \
    --target-group-arn $targetGroup
```

:::note
Note that in some cases the `targets` parameter `Id` can be the `Gateway` address of the docker container.
You can find the gateway address by running `docker inspect <container_id>`.
:::

### Create a listener and a rule

We create a listener for the load balancer using the [`CreateListener`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateListener.html) API.
The following command creates a listener for the load balancer created in the previous step:

```bash
listenerArn=$(lstk aws elbv2 create-listener \
        --protocol HTTP \
        --port 80 \
        --default-actions '{"Type":"forward","TargetGroupArn":"'$targetGroup'","ForwardConfig":{"TargetGroups":[{"TargetGroupArn":"'$targetGroup'","Weight":11}]}}' \
        --load-balancer-arn $loadBalancer | jq -r '.Listeners[]|.ListenerArn')
```

To create a rule for the listener, you can use the [`CreateRule`](https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_CreateRule.html) API.
The following command creates a rule for the listener created above:

```bash
listenerRule=$(lstk aws elbv2 create-rule \
        --conditions Field=path-pattern,Values=/ \
        --priority 1 \
        --actions '{"Type":"forward","TargetGroupArn":"'$targetGroup'","ForwardConfig":{"TargetGroups":[{"TargetGroupArn":"'$targetGroup'","Weight":11}]}}' \
        --listener-arn $listenerArn \
    | jq -r '.Rules[].RuleArn')
```

### Send a request to the load balancer

Finally, you can issue an HTTP request to the `DNSName` parameter of `CreateLoadBalancer` operation, and `Port` parameter of `CreateListener` command with the following command:

```bash
curl example-lb.elb.localhost.localstack.cloud:4566
```

```bash title="Output"
{
  "host": {
    "hostname": "example-lb.elb.localhost.localstack.cloud",
    "ip": "::ffff:172.17.0.1",
    "ips": []
  },
  "http": {
    "method": "GET",
    "baseUrl": "",
    "originalUrl": "/",
    "protocol": "http"
  },
  "request": {
    "params": {
      "0": "/"
    },
    "query": {},
    "cookies": {},
    "body": {},
    "headers": {
      "accept-encoding": "identity",
      "host": "example-lb.elb.localhost.localstack.cloud:4566",
      "user-agent": "curl/7.88.1",
      "accept": "*/*"
    }
  },
  "environment": {
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "HOSTNAME": "bee08b83d633",
    "TERM": "xterm",
    "NODE_VERSION": "18.17.1",
    "YARN_VERSION": "1.22.19",
    "HOME": "/root"
  }
}
```

#### Alternative URL structure

If a request cannot be made to a subdomain of `localhost.localstack.cloud`, an alternative URL structure is available, however it is not returned by AWS management API methods.
To make a request against an ELB with id `<elb-id>`, use the URL:

```bash
http(s)://localhost.localstack.cloud:4566/_aws/elb/<elb-id>/<elb-path>
```

Here's an example of how you would access the load balancer with a name of `example-lb` with the subdomain-based URL format:

```bash
http(s)://example-lb.elb.localhost.localstack.cloud:4566/test/path
```

With the alternative URL structure:

```bash
http(s)://localhost.localstack.cloud:4566/_aws/elb/example-lb/test/path
```

## Multiple Listeners and Port-Based Routing

An Application Load Balancer can have multiple listeners, each bound to a different port.
In LocalStack, same-scheme listeners (for example, two HTTP listeners on ports 80 and 8080) are routed by matching the request's arrival port to the listener's configured port.

### Configuring LocalStack for multiple listener ports

To reach two same-scheme listeners on distinct ports, both ports must be published in [`GATEWAY_LISTEN`](/aws/customization/configuration-options/#core) when starting LocalStack.
`lstk` decides which host ports to open before it reads any inline environment variable, so setting `LOCALSTACK_GATEWAY_LISTEN` on the command line does not open the extra ports, the variable still reaches the container, but the host-side port publication has already been decided by that point. Set `GATEWAY_LISTEN` in your `lstk` config file instead:

```toml
# .lstk/config.toml
[[containers]]
type = "aws"
port = "4566"
env  = ["multi-listener"]

[env.multi-listener]
GATEWAY_LISTEN = "0.0.0.0:4566,0.0.0.0:80,0.0.0.0:8080"
```

```bash
lstk start
```

### Creating multiple listeners

With LocalStack running and both ports published, create a load balancer and two HTTP listeners on different ports.
The following example uses the `subnet_id` variable set in the [Getting started](#getting-started) steps above, and creates two listeners with distinct `fixed-response` default actions so you can verify that each port routes to the correct listener:

```bash
# Create the load balancer
loadBalancer=$(lstk aws elbv2 create-load-balancer \
    --name multi-listener-lb \
    --subnets $subnet_id | jq -r '.LoadBalancers[].LoadBalancerArn')

# Listener on port 80
lstk aws elbv2 create-listener \
    --load-balancer-arn $loadBalancer \
    --protocol HTTP \
    --port 80 \
    --default-actions '{"Type":"fixed-response","FixedResponseConfig":{"StatusCode":"200","MessageBody":"Listener 80","ContentType":"text/plain"}}'

# Listener on port 8080
lstk aws elbv2 create-listener \
    --load-balancer-arn $loadBalancer \
    --protocol HTTP \
    --port 8080 \
    --default-actions '{"Type":"fixed-response","FixedResponseConfig":{"StatusCode":"200","MessageBody":"Listener 8080","ContentType":"text/plain"}}'
```

A request to port 80 is handled by the listener bound to that port:

```bash
curl multi-listener-lb.elb.localhost.localstack.cloud:80
```

```bash title="Output"
Listener 80
```

A request to port 8080 is handled by the listener bound to that port:

```bash
curl multi-listener-lb.elb.localhost.localstack.cloud:8080
```

```bash title="Output"
Listener 8080
```

### By-design limitation: shared gateway port

When a request arrives on the shared `:4566` gateway port, LocalStack cannot determine which same-scheme listener was intended and falls back to the first-created listener:

```bash
curl multi-listener-lb.elb.localhost.localstack.cloud:4566
```

```bash title="Output"
Listener 80
```

:::note
If your setup uses only the default `:4566` gateway port and you need multiple listeners, consolidate to a single listener per scheme. Same-scheme listeners on distinct ports can only be told apart when those ports are added to `GATEWAY_LISTEN` and targeted directly.
:::

## Examples

The following code snippets and sample applications provide practical examples of how to use ELB in LocalStack for various use cases:

- [Setting up Elastic Load Balancing (ELB) Application Load Balancers using LocalStack, deployed via the Serverless framework](/aws/tutorials/elb-load-balancing/)

## Current Limitations

- The Application Load Balancer currently supports only the `forward`, `redirect` and `fixed-response` action types.
- When opting for Route53 CNAMEs to direct requests towards the ALBs, it's important to remember that explicit configuration of the `Host` header to match the resource record might be necessary while making calls.

## API Coverage (ELBv1)


### Elastic Load Balancer API coverage

Source service: `elb`. 27 of 29 tracked operations are implemented.

Service documentation: /aws/services/elb/
License availability: available starting with the Base plan. See /aws/licensing/ for current plan details.

| Operation | Status |
| --- | --- |
| AddTags | Implemented |
| ApplySecurityGroupsToLoadBalancer | Implemented |
| AttachLoadBalancerToSubnets | Implemented |
| ConfigureHealthCheck | Implemented |
| CreateAppCookieStickinessPolicy | Implemented |
| CreateLBCookieStickinessPolicy | Implemented |
| CreateLoadBalancer | Implemented |
| CreateLoadBalancerListeners | Implemented |
| CreateLoadBalancerPolicy | Implemented |
| DeleteLoadBalancer | Implemented |
| DeleteLoadBalancerListeners | Implemented |
| DeleteLoadBalancerPolicy | Implemented |
| DeregisterInstancesFromLoadBalancer | Implemented |
| DescribeAccountLimits | Not implemented |
| DescribeInstanceHealth | Implemented |
| DescribeLoadBalancerAttributes | Implemented |
| DescribeLoadBalancerPolicies | Implemented |
| DescribeLoadBalancerPolicyTypes | Not implemented |
| DescribeLoadBalancers | Implemented |
| DescribeTags | Implemented |
| DetachLoadBalancerFromSubnets | Implemented |
| DisableAvailabilityZonesForLoadBalancer | Implemented |
| EnableAvailabilityZonesForLoadBalancer | Implemented |
| ModifyLoadBalancerAttributes | Implemented |
| RegisterInstancesWithLoadBalancer | Implemented |
| RemoveTags | Implemented |
| SetLoadBalancerListenerSSLCertificate | Implemented |
| SetLoadBalancerPoliciesForBackendServer | Implemented |
| SetLoadBalancerPoliciesOfListener | Implemented |

## API Coverage (ELBv2)


### Elastic Load Balancer v2 API coverage

Source service: `elbv2`. 38 of 51 tracked operations are implemented.

Service documentation: /aws/services/elb/
License availability: available starting with the Base plan. See /aws/licensing/ for current plan details.

| Operation | Status |
| --- | --- |
| AddListenerCertificates | Implemented |
| AddTags | Implemented |
| AddTrustStoreRevocations | Not implemented |
| CreateListener | Implemented |
| CreateLoadBalancer | Implemented |
| CreateRule | Implemented |
| CreateTargetGroup | Implemented |
| CreateTrustStore | Not implemented |
| DeleteListener | Implemented |
| DeleteLoadBalancer | Implemented |
| DeleteRule | Implemented |
| DeleteSharedTrustStoreAssociation | Not implemented |
| DeleteTargetGroup | Implemented |
| DeleteTrustStore | Not implemented |
| DeregisterTargets | Implemented |
| DescribeAccountLimits | Implemented |
| DescribeCapacityReservation | Implemented |
| DescribeListenerAttributes | Implemented |
| DescribeListenerCertificates | Implemented |
| DescribeListeners | Implemented |
| DescribeLoadBalancerAttributes | Implemented |
| DescribeLoadBalancers | Implemented |
| DescribeRules | Implemented |
| DescribeSSLPolicies | Implemented |
| DescribeTags | Implemented |
| DescribeTargetGroupAttributes | Implemented |
| DescribeTargetGroups | Implemented |
| DescribeTargetHealth | Implemented |
| DescribeTrustStoreAssociations | Not implemented |
| DescribeTrustStoreRevocations | Not implemented |
| DescribeTrustStores | Not implemented |
| GetResourcePolicy | Not implemented |
| GetTrustStoreCaCertificatesBundle | Not implemented |
| GetTrustStoreRevocationContent | Not implemented |
| ModifyCapacityReservation | Implemented |
| ModifyIpPools | Not implemented |
| ModifyListener | Implemented |
| ModifyListenerAttributes | Implemented |
| ModifyLoadBalancerAttributes | Implemented |
| ModifyRule | Implemented |
| ModifyTargetGroup | Implemented |
| ModifyTargetGroupAttributes | Implemented |
| ModifyTrustStore | Not implemented |
| RegisterTargets | Implemented |
| RemoveListenerCertificates | Implemented |
| RemoveTags | Implemented |
| RemoveTrustStoreRevocations | Not implemented |
| SetIpAddressType | Implemented |
| SetRulePriorities | Implemented |
| SetSecurityGroups | Implemented |
| SetSubnets | Implemented |
