The aws:lb/loadBalancer:LoadBalancer resource, part of the Pulumi AWS provider, provisions the load balancer itself: its type (Application, Network, or Gateway), network placement, and operational settings. This guide focuses on three capabilities: Application and Network Load Balancer deployment, subnet placement strategies, and static IP assignment for Network Load Balancers.
Load balancers require VPC subnets, 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 set to false makes it internet-facing. The subnets property places the load balancer across multiple availability zones for high availability. The securityGroups property controls inbound traffic, and accessLogs sends request logs 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" },
},
});
});
The loadBalancerType property set 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 preserve source IP addresses and handle millions of requests per second. The subnets property determines availability zone placement.
Assign static Elastic IPs to Network Load Balancer nodes
Some applications require stable IP addresses for firewall allowlisting or DNS configuration. Network Load Balancers can use Elastic IPs for predictable addressing.
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 IP control. Each mapping pairs a subnetId with an allocationId (Elastic IP). This gives each load balancer node a static public IP address that persists across updates.
Configure private IP addresses for internal load balancers
Internal load balancers that need specific IP addresses for integration with on-premises networks or IP-based routing can specify private IPv4 addresses.
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
The subnetMappings property with privateIpv4Address assigns specific private IPs to load balancer nodes. This is useful when integrating with on-premises networks that route to specific IP ranges, or when IP-based firewall rules require predictable addresses.
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:
- Target groups and listener configuration
- SSL/TLS certificates and HTTPS listeners
- Cross-zone load balancing (enableCrossZoneLoadBalancing)
- Connection and health check logging
- WAF integration (enableWafFailOpen)
- HTTP header processing (xffHeaderProcessingMode, preserveHostHeader)
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 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 & Basics
application, network, or gateway load balancers. The default type is application.Network Configuration
subnets or subnetMappings (not both). Use subnetMappings when you need to assign Elastic IPs or specific private IP addresses.subnetMappings with allocationId pointing to your Elastic IP allocation for each subnet.subnetMappings with privateIpv4Address for each subnet instead of the subnets property.ipv4. You can change to dualstack only if your selected subnets are IPv6-enabled.Network Load Balancer Limitations
secondaryIpsAutoAssignedPerSubnet will force recreation of the resource. The valid range is 0-7 with a default of 0.Application Load Balancer Configuration
Immutability & Resource Recreation
internal, name, namePrefix, loadBalancerType, and customerOwnedIpv4Pool. Changing any of these will force recreation of the resource.enableDeletionProtection to true. This prevents the load balancer from being deleted via the AWS API, including by Pulumi.Using a different cloud?
Explore networking guides for other cloud providers: