The aws:alb/loadBalancer:LoadBalancer resource, part of the Pulumi AWS provider, provisions the load balancer itself: its type (Application, Network, or Gateway), subnet placement, and core networking configuration. This guide focuses on three capabilities: Application and Network Load Balancer deployment, subnet placement strategies, and static IP addressing for Network Load Balancers.
Load balancers depend on VPC subnets across availability zones, security groups (for Application Load Balancers), and optionally S3 buckets for logging or Elastic IPs for static addressing. The examples are intentionally small. Combine them with your own target groups, listeners, and routing rules.
Deploy an internet-facing Application Load Balancer
Most web applications start with an Application Load Balancer that distributes HTTP/HTTPS traffic across targets in different availability zones.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.lb.LoadBalancer("test", {
name: "test-lb-tf",
internal: false,
loadBalancerType: "application",
securityGroups: [lbSg.id],
subnets: .map(subnet => (subnet.id)),
enableDeletionProtection: true,
accessLogs: {
bucket: lbLogs.id,
prefix: "test-lb",
enabled: true,
},
tags: {
Environment: "production",
},
});
import pulumi
import pulumi_aws as aws
test = aws.lb.LoadBalancer("test",
name="test-lb-tf",
internal=False,
load_balancer_type="application",
security_groups=[lb_sg["id"]],
subnets=[subnet["id"] for subnet in public],
enable_deletion_protection=True,
access_logs={
"bucket": lb_logs["id"],
"prefix": "test-lb",
"enabled": True,
},
tags={
"Environment": "production",
})
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.LB.LoadBalancer("test", new()
{
Name = "test-lb-tf",
Internal = false,
LoadBalancerType = "application",
SecurityGroups = new[]
{
lbSg.Id,
},
Subnets = .Select(subnet =>
{
return subnet.Id;
}).ToList(),
EnableDeletionProtection = true,
AccessLogs = new Aws.LB.Inputs.LoadBalancerAccessLogsArgs
{
Bucket = lbLogs.Id,
Prefix = "test-lb",
Enabled = true,
},
Tags =
{
{ "Environment", "production" },
},
});
});
The loadBalancerType property set to “application” creates a Layer 7 load balancer that routes HTTP/HTTPS requests. The internal property controls whether the load balancer is internet-facing (false) or internal (true). The subnets property places the load balancer across multiple availability zones for high availability. The securityGroups property controls inbound traffic, and accessLogs enables request logging to S3. The enableDeletionProtection property prevents accidental deletion.
Deploy a Network Load Balancer for TCP traffic
Applications requiring ultra-low latency or handling millions of requests per second use Network Load Balancers, which operate at the connection level (Layer 4).
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.lb.LoadBalancer("test", {
name: "test-lb-tf",
internal: false,
loadBalancerType: "network",
subnets: .map(subnet => (subnet.id)),
enableDeletionProtection: true,
tags: {
Environment: "production",
},
});
import pulumi
import pulumi_aws as aws
test = aws.lb.LoadBalancer("test",
name="test-lb-tf",
internal=False,
load_balancer_type="network",
subnets=[subnet["id"] for subnet in public],
enable_deletion_protection=True,
tags={
"Environment": "production",
})
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.LB.LoadBalancer("test", new()
{
Name = "test-lb-tf",
Internal = false,
LoadBalancerType = "network",
Subnets = .Select(subnet =>
{
return subnet.Id;
}).ToList(),
EnableDeletionProtection = true,
Tags =
{
{ "Environment", "production" },
},
});
});
Setting loadBalancerType to “network” creates a Layer 4 load balancer that routes TCP/UDP traffic with minimal latency. Network Load Balancers don’t require security groups by default; they rely on target security groups for access control. The subnets property determines availability zone placement, and enableDeletionProtection prevents accidental removal.
Assign static Elastic IPs to Network Load Balancer nodes
Some applications require stable IP addresses for firewall allowlisting or DNS configuration. Network Load Balancers support attaching Elastic IPs to each subnet.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lb.LoadBalancer("example", {
name: "example",
loadBalancerType: "network",
subnetMappings: [
{
subnetId: example1AwsSubnet.id,
allocationId: example1.id,
},
{
subnetId: example2AwsSubnet.id,
allocationId: example2.id,
},
],
});
import pulumi
import pulumi_aws as aws
example = aws.lb.LoadBalancer("example",
name="example",
load_balancer_type="network",
subnet_mappings=[
{
"subnet_id": example1_aws_subnet["id"],
"allocation_id": example1["id"],
},
{
"subnet_id": example2_aws_subnet["id"],
"allocation_id": example2["id"],
},
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := lb.NewLoadBalancer(ctx, "example", &lb.LoadBalancerArgs{
Name: pulumi.String("example"),
LoadBalancerType: pulumi.String("network"),
SubnetMappings: lb.LoadBalancerSubnetMappingArray{
&lb.LoadBalancerSubnetMappingArgs{
SubnetId: pulumi.Any(example1AwsSubnet.Id),
AllocationId: pulumi.Any(example1.Id),
},
&lb.LoadBalancerSubnetMappingArgs{
SubnetId: pulumi.Any(example2AwsSubnet.Id),
AllocationId: pulumi.Any(example2.Id),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.LB.LoadBalancer("example", new()
{
Name = "example",
LoadBalancerType = "network",
SubnetMappings = new[]
{
new Aws.LB.Inputs.LoadBalancerSubnetMappingArgs
{
SubnetId = example1AwsSubnet.Id,
AllocationId = example1.Id,
},
new Aws.LB.Inputs.LoadBalancerSubnetMappingArgs
{
SubnetId = example2AwsSubnet.Id,
AllocationId = example2.Id,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.lb.inputs.LoadBalancerSubnetMappingArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LoadBalancer("example", LoadBalancerArgs.builder()
.name("example")
.loadBalancerType("network")
.subnetMappings(
LoadBalancerSubnetMappingArgs.builder()
.subnetId(example1AwsSubnet.id())
.allocationId(example1.id())
.build(),
LoadBalancerSubnetMappingArgs.builder()
.subnetId(example2AwsSubnet.id())
.allocationId(example2.id())
.build())
.build());
}
}
resources:
example:
type: aws:lb:LoadBalancer
properties:
name: example
loadBalancerType: network
subnetMappings:
- subnetId: ${example1AwsSubnet.id}
allocationId: ${example1.id}
- subnetId: ${example2AwsSubnet.id}
allocationId: ${example2.id}
The subnetMappings property replaces the subnets property when you need control over IP addressing. Each mapping specifies a subnetId and an allocationId pointing to an Elastic IP. This gives your load balancer stable, predictable IP addresses that clients can allowlist. You must create one mapping per availability zone.
Configure private IP addresses for internal load balancers
Internal load balancers that need predictable IP addresses for integration with on-premises networks or security policies can specify private IPs per subnet.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lb.LoadBalancer("example", {
name: "example",
loadBalancerType: "network",
subnetMappings: [
{
subnetId: example1.id,
privateIpv4Address: "10.0.1.15",
},
{
subnetId: example2.id,
privateIpv4Address: "10.0.2.15",
},
],
});
import pulumi
import pulumi_aws as aws
example = aws.lb.LoadBalancer("example",
name="example",
load_balancer_type="network",
subnet_mappings=[
{
"subnet_id": example1["id"],
"private_ipv4_address": "10.0.1.15",
},
{
"subnet_id": example2["id"],
"private_ipv4_address": "10.0.2.15",
},
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := lb.NewLoadBalancer(ctx, "example", &lb.LoadBalancerArgs{
Name: pulumi.String("example"),
LoadBalancerType: pulumi.String("network"),
SubnetMappings: lb.LoadBalancerSubnetMappingArray{
&lb.LoadBalancerSubnetMappingArgs{
SubnetId: pulumi.Any(example1.Id),
PrivateIpv4Address: pulumi.String("10.0.1.15"),
},
&lb.LoadBalancerSubnetMappingArgs{
SubnetId: pulumi.Any(example2.Id),
PrivateIpv4Address: pulumi.String("10.0.2.15"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.LB.LoadBalancer("example", new()
{
Name = "example",
LoadBalancerType = "network",
SubnetMappings = new[]
{
new Aws.LB.Inputs.LoadBalancerSubnetMappingArgs
{
SubnetId = example1.Id,
PrivateIpv4Address = "10.0.1.15",
},
new Aws.LB.Inputs.LoadBalancerSubnetMappingArgs
{
SubnetId = example2.Id,
PrivateIpv4Address = "10.0.2.15",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.lb.inputs.LoadBalancerSubnetMappingArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LoadBalancer("example", LoadBalancerArgs.builder()
.name("example")
.loadBalancerType("network")
.subnetMappings(
LoadBalancerSubnetMappingArgs.builder()
.subnetId(example1.id())
.privateIpv4Address("10.0.1.15")
.build(),
LoadBalancerSubnetMappingArgs.builder()
.subnetId(example2.id())
.privateIpv4Address("10.0.2.15")
.build())
.build());
}
}
resources:
example:
type: aws:lb:LoadBalancer
properties:
name: example
loadBalancerType: network
subnetMappings:
- subnetId: ${example1.id}
privateIpv4Address: 10.0.1.15
- subnetId: ${example2.id}
privateIpv4Address: 10.0.2.15
When you specify privateIpv4Address in subnetMappings, the load balancer uses those exact IPs within each subnet. This is useful for integrating with on-premises networks that require specific IP addresses in routing tables or firewall rules. The IPs must be available in their respective subnets and fall within the subnet’s CIDR range.
Beyond these examples
These snippets focus on specific load balancer features: Application and Network Load Balancer types, subnet placement and IP addressing, and access logging and deletion protection. They’re intentionally minimal rather than full traffic routing solutions.
The examples reference pre-existing infrastructure such as VPC subnets across multiple availability zones, security groups (for Application Load Balancers), S3 buckets for access logs, and Elastic IP allocations (for static IP examples). They focus on configuring the load balancer rather than provisioning the surrounding infrastructure.
To keep things focused, common load balancer patterns are omitted, including:
- Cross-zone load balancing configuration
- Idle timeout and connection settings
- HTTP/2 and header processing options
- Target groups and listener configuration
- SSL/TLS certificate attachment
- WAF integration and security features
These omissions are intentional: the goal is to illustrate how each load balancer feature is wired, not provide drop-in traffic routing modules. See the Load Balancer resource reference for all available configuration options.
Let's create AWS Application Load Balancers
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Load Balancer Types & Configuration
application, gateway, or network load balancers. The default type is application.internal, name, namePrefix, customerOwnedIpv4Pool, and loadBalancerType. Changing these forces resource recreation.network and gateway load balancers, cross-zone load balancing is disabled by default (false). For application load balancers, it’s always enabled (true) and cannot be disabled.Networking & Subnets
subnets or subnetMapping, but not both. Use subnets for simple configuration, or subnetMapping for advanced scenarios like assigning Elastic IPs or private IP addresses.subnetMappings can only be added.subnetMappings with subnetId and allocationId (Elastic IP allocation ID) for each subnet.subnetMappings with subnetId and privateIpv4Address for each subnet.ipv4. You can change to dualstack only if the selected subnets are IPv6-enabled.Application Load Balancer Features
true) on Application Load Balancers.Network Load Balancer Features
Security & Protection
enableDeletionProtection to true. This prevents deletion via the AWS API and Pulumi. The default is false.Using a different cloud?
Explore networking guides for other cloud providers: