Load Balancing Basics
Six short examples that take you from nothing to a working Application Load Balancer: create it, wait for it, give it a target group, register a backend, add a listener, and confirm the target is healthy.
Search across all documentation pages
Six short examples that take you from nothing to a working Application Load Balancer: create it, wait for it, give it a target group, register a backend, add a listener, and confirm the target is healthy.
Each example shows the same operation in both Python (boto3) and TypeScript (AWS SDK for JavaScript v3), so the mechanics translate one to one. All of them use the ELB v2 client - elbv2 in boto3, @aws-sdk/client-elastic-load-balancing-v2 in SDK v3.
pip install boto3 (boto3 1.43.x, Python 3.10+). TypeScript: npm install @aws-sdk/client-elastic-load-balancing-v2 (Node.js 18+).aws configure, environment variables, or an IAM role with elasticloadbalancing:* (scope down for production).CreateLoadBalancer provisions the ALB across two or more subnets and returns its ARN and DNS name.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
resp = elbv2.create_load_balancer(
Name="web-alb",
Type="application",
Subnets=["subnet-0aaa", "subnet-0bbb"],
SecurityGroups=["sg-0web"],
Scheme="internet-facing",
)
lb = resp["LoadBalancers"][0]
print(lb["LoadBalancerArn"])
print(lb["DNSName"]) # the address clients will use// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, CreateLoadBalancerCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
const resp = await elbv2.send(new CreateLoadBalancerCommand({
Name: "web-alb",
Type: "application",
Subnets: ["subnet-0aaa", "subnet-0bbb"],
SecurityGroups: ["sg-0web"],
Scheme: "internet-facing",
}));
const lb = resp.LoadBalancers?.[0];
console.log(lb?.LoadBalancerArn);
console.log(lb?.DNSName); // the address clients will useType defaults to application; set it explicitly so the intent is clear.Scheme is internet-facing for a public ALB or internal for a private one.DNSName is the endpoint you point DNS at - the ALB has no static IP.A new ALB starts in provisioning; wait for active before wiring listeners with a waiter.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
lb_arn = "arn:aws:elasticloadbalancing:...:loadbalancer/app/web-alb/abc"
elbv2.get_waiter("load_balancer_available").wait(LoadBalancerArns=[lb_arn])
print("load balancer is active")// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, waitUntilLoadBalancerAvailable } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
const lbArn = "arn:aws:elasticloadbalancing:...:loadbalancer/app/web-alb/abc";
await waitUntilLoadBalancerAvailable({ client: elbv2, maxWaitTime: 300 }, { LoadBalancerArns: [lbArn] });
console.log("load balancer is active");DescribeLoadBalancers until State.Code is active.maxWaitTime (SDK v3) caps how long the waiter blocks, in seconds.CreateTargetGroup defines the backend pool and its health check; it needs the VPC and a target type.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
resp = elbv2.create_target_group(
Name="web-tg",
Protocol="HTTP",
Port=80,
VpcId="vpc-0abc",
TargetType="instance",
HealthCheckProtocol="HTTP",
HealthCheckPath="/healthz",
)
tg_arn = resp["TargetGroups"][0]["TargetGroupArn"]
print(tg_arn)// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, CreateTargetGroupCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
const resp = await elbv2.send(new CreateTargetGroupCommand({
Name: "web-tg",
Protocol: "HTTP",
Port: 80,
VpcId: "vpc-0abc",
TargetType: "instance",
HealthCheckProtocol: "HTTP",
HealthCheckPath: "/healthz",
}));
const tgArn = resp.TargetGroups?.[0].TargetGroupArn;
console.log(tgArn);TargetType is instance (EC2 id), ip (any routable IP), or lambda (a function).Protocol and Port describe how the load balancer talks to the targets./healthz style HealthCheckPath should be cheap and dependency-free.RegisterTargets adds one or more backends to the target group.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
elbv2.register_targets(
TargetGroupArn=tg_arn,
Targets=[{"Id": "i-0abc123"}], # an instance id for TargetType "instance"
)// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, RegisterTargetsCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
await elbv2.send(new RegisterTargetsCommand({
TargetGroupArn: tgArn,
Targets: [{ Id: "i-0abc123" }], // an instance id for TargetType "instance"
}));instance targets, Id is the instance id; for ip targets it is an IP address.Port per target to override the group's default port.initial until it passes.Targets is a list, so you can register a batch of backends in one call.CreateListener connects a port on the ALB to the target group via a default forward action.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
resp = elbv2.create_listener(
LoadBalancerArn=lb_arn,
Protocol="HTTP",
Port=80,
DefaultActions=[{"Type": "forward", "TargetGroupArn": tg_arn}],
)
print(resp["Listeners"][0]["ListenerArn"])// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, CreateListenerCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
const resp = await elbv2.send(new CreateListenerCommand({
LoadBalancerArn: lbArn,
Protocol: "HTTP",
Port: 80,
DefaultActions: [{ Type: "forward", TargetGroupArn: tgArn }],
}));
console.log(resp.Listeners?.[0].ListenerArn);Protocol/Port is what clients connect to; the target group's is what backends receive.DefaultActions runs when no routing rule matches - here it forwards everything to web-tg.Protocol: "HTTPS", port 443, and attach an ACM certificate.DescribeTargetHealth reports whether each registered target is ready to serve traffic.
# --- Python (boto3) ---
import boto3
elbv2 = boto3.client("elbv2", region_name="us-east-1")
resp = elbv2.describe_target_health(TargetGroupArn=tg_arn)
for d in resp["TargetHealthDescriptions"]:
print(d["Target"]["Id"], d["TargetHealth"]["State"]) # e.g. i-0abc123 healthy// --- TypeScript (AWS SDK v3) ---
import { ElasticLoadBalancingV2Client, DescribeTargetHealthCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
const elbv2 = new ElasticLoadBalancingV2Client({ region: "us-east-1" });
const resp = await elbv2.send(new DescribeTargetHealthCommand({ TargetGroupArn: tgArn }));
for (const d of resp.TargetHealthDescriptions ?? []) {
console.log(d.Target?.Id, d.TargetHealth?.State); // e.g. i-0abc123 healthy
}initial, healthy, unhealthy, unused, draining, and unavailable.initial until it passes the configured number of health checks.unhealthy includes a Reason and Description explaining why the check failed.healthy targets receive traffic - poll this after registering before you cut over.Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 23, 2026