The gcp:networkservices/serviceLbPolicies:ServiceLbPolicies resource, part of the Pulumi GCP provider, defines global load balancing policies that control traffic distribution and failover behavior for backend services. This guide focuses on three capabilities: traffic distribution algorithms, automatic capacity draining, and regional isolation controls.
Policies are attached to backend services via the serviceLbPolicy property. The examples are intentionally small. Combine them with your own backend services and health checks.
Create a minimal global load balancing policy
Most deployments start with a basic policy that establishes the foundation for traffic distribution.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.networkservices.ServiceLbPolicies("default", {
name: "my-lb-policy",
location: "global",
});
import pulumi
import pulumi_gcp as gcp
default = gcp.networkservices.ServiceLbPolicies("default",
name="my-lb-policy",
location="global")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := networkservices.NewServiceLbPolicies(ctx, "default", &networkservices.ServiceLbPoliciesArgs{
Name: pulumi.String("my-lb-policy"),
Location: pulumi.String("global"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var @default = new Gcp.NetworkServices.ServiceLbPolicies("default", new()
{
Name = "my-lb-policy",
Location = "global",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkservices.ServiceLbPolicies;
import com.pulumi.gcp.networkservices.ServiceLbPoliciesArgs;
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 default_ = new ServiceLbPolicies("default", ServiceLbPoliciesArgs.builder()
.name("my-lb-policy")
.location("global")
.build());
}
}
resources:
default:
type: gcp:networkservices:ServiceLbPolicies
properties:
name: my-lb-policy
location: global
The name property identifies the policy, and location must be set to “global” for service-level load balancing policies. Without additional configuration, the policy uses default behavior (WATERFALL_BY_REGION algorithm).
Configure traffic distribution and failover behavior
Production workloads often need custom traffic distribution and automatic capacity draining when backends become unhealthy.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.networkservices.ServiceLbPolicies("default", {
name: "my-lb-policy",
location: "global",
description: "my description",
loadBalancingAlgorithm: "SPRAY_TO_REGION",
autoCapacityDrain: {
enable: true,
},
failoverConfig: {
failoverHealthThreshold: 70,
},
labels: {
foo: "bar",
},
});
const defaultBackendService = new gcp.compute.BackendService("default", {
name: "my-lb-backend",
description: "my description",
loadBalancingScheme: "INTERNAL_SELF_MANAGED",
protocol: "HTTP",
serviceLbPolicy: pulumi.interpolate`//networkservices.googleapis.com/${_default.id}`,
});
import pulumi
import pulumi_gcp as gcp
default = gcp.networkservices.ServiceLbPolicies("default",
name="my-lb-policy",
location="global",
description="my description",
load_balancing_algorithm="SPRAY_TO_REGION",
auto_capacity_drain={
"enable": True,
},
failover_config={
"failover_health_threshold": 70,
},
labels={
"foo": "bar",
})
default_backend_service = gcp.compute.BackendService("default",
name="my-lb-backend",
description="my description",
load_balancing_scheme="INTERNAL_SELF_MANAGED",
protocol="HTTP",
service_lb_policy=default.id.apply(lambda id: f"//networkservices.googleapis.com/{id}"))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := networkservices.NewServiceLbPolicies(ctx, "default", &networkservices.ServiceLbPoliciesArgs{
Name: pulumi.String("my-lb-policy"),
Location: pulumi.String("global"),
Description: pulumi.String("my description"),
LoadBalancingAlgorithm: pulumi.String("SPRAY_TO_REGION"),
AutoCapacityDrain: &networkservices.ServiceLbPoliciesAutoCapacityDrainArgs{
Enable: pulumi.Bool(true),
},
FailoverConfig: &networkservices.ServiceLbPoliciesFailoverConfigArgs{
FailoverHealthThreshold: pulumi.Int(70),
},
Labels: pulumi.StringMap{
"foo": pulumi.String("bar"),
},
})
if err != nil {
return err
}
_, err = compute.NewBackendService(ctx, "default", &compute.BackendServiceArgs{
Name: pulumi.String("my-lb-backend"),
Description: pulumi.String("my description"),
LoadBalancingScheme: pulumi.String("INTERNAL_SELF_MANAGED"),
Protocol: pulumi.String("HTTP"),
ServiceLbPolicy: _default.ID().ApplyT(func(id string) (string, error) {
return fmt.Sprintf("//networkservices.googleapis.com/%v", id), nil
}).(pulumi.StringOutput),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var @default = new Gcp.NetworkServices.ServiceLbPolicies("default", new()
{
Name = "my-lb-policy",
Location = "global",
Description = "my description",
LoadBalancingAlgorithm = "SPRAY_TO_REGION",
AutoCapacityDrain = new Gcp.NetworkServices.Inputs.ServiceLbPoliciesAutoCapacityDrainArgs
{
Enable = true,
},
FailoverConfig = new Gcp.NetworkServices.Inputs.ServiceLbPoliciesFailoverConfigArgs
{
FailoverHealthThreshold = 70,
},
Labels =
{
{ "foo", "bar" },
},
});
var defaultBackendService = new Gcp.Compute.BackendService("default", new()
{
Name = "my-lb-backend",
Description = "my description",
LoadBalancingScheme = "INTERNAL_SELF_MANAGED",
Protocol = "HTTP",
ServiceLbPolicy = @default.Id.Apply(id => $"//networkservices.googleapis.com/{id}"),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkservices.ServiceLbPolicies;
import com.pulumi.gcp.networkservices.ServiceLbPoliciesArgs;
import com.pulumi.gcp.networkservices.inputs.ServiceLbPoliciesAutoCapacityDrainArgs;
import com.pulumi.gcp.networkservices.inputs.ServiceLbPoliciesFailoverConfigArgs;
import com.pulumi.gcp.compute.BackendService;
import com.pulumi.gcp.compute.BackendServiceArgs;
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 default_ = new ServiceLbPolicies("default", ServiceLbPoliciesArgs.builder()
.name("my-lb-policy")
.location("global")
.description("my description")
.loadBalancingAlgorithm("SPRAY_TO_REGION")
.autoCapacityDrain(ServiceLbPoliciesAutoCapacityDrainArgs.builder()
.enable(true)
.build())
.failoverConfig(ServiceLbPoliciesFailoverConfigArgs.builder()
.failoverHealthThreshold(70)
.build())
.labels(Map.of("foo", "bar"))
.build());
var defaultBackendService = new BackendService("defaultBackendService", BackendServiceArgs.builder()
.name("my-lb-backend")
.description("my description")
.loadBalancingScheme("INTERNAL_SELF_MANAGED")
.protocol("HTTP")
.serviceLbPolicy(default_.id().applyValue(_id -> String.format("//networkservices.googleapis.com/%s", _id)))
.build());
}
}
resources:
default:
type: gcp:networkservices:ServiceLbPolicies
properties:
name: my-lb-policy
location: global
description: my description
loadBalancingAlgorithm: SPRAY_TO_REGION
autoCapacityDrain:
enable: true
failoverConfig:
failoverHealthThreshold: 70
labels:
foo: bar
defaultBackendService:
type: gcp:compute:BackendService
name: default
properties:
name: my-lb-backend
description: my description
loadBalancingScheme: INTERNAL_SELF_MANAGED
protocol: HTTP
serviceLbPolicy: //networkservices.googleapis.com/${default.id}
The loadBalancingAlgorithm property controls how traffic spreads across regions. SPRAY_TO_REGION distributes requests more evenly than the default WATERFALL_BY_REGION, which prefers closer regions first. The autoCapacityDrain block enables automatic removal of unhealthy backends from the load balancing pool. The failoverConfig sets a health threshold (70%) that triggers failover to healthy backends. The policy is attached to a backend service by referencing its ID in the serviceLbPolicy property using the full resource path format.
Add isolation controls for regional traffic containment
Applications with data residency requirements or latency-sensitive workloads benefit from isolation configuration.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _default = new gcp.networkservices.ServiceLbPolicies("default", {
name: "my-lb-policy",
location: "global",
description: "my description",
loadBalancingAlgorithm: "SPRAY_TO_REGION",
autoCapacityDrain: {
enable: true,
},
failoverConfig: {
failoverHealthThreshold: 70,
},
isolationConfig: {
isolationGranularity: "REGION",
isolationMode: "NEAREST",
},
labels: {
foo: "bar",
},
});
const defaultBackendService = new gcp.compute.BackendService("default", {
name: "my-lb-backend",
description: "my description",
loadBalancingScheme: "INTERNAL_SELF_MANAGED",
protocol: "HTTP",
serviceLbPolicy: pulumi.interpolate`//networkservices.googleapis.com/${_default.id}`,
});
import pulumi
import pulumi_gcp as gcp
default = gcp.networkservices.ServiceLbPolicies("default",
name="my-lb-policy",
location="global",
description="my description",
load_balancing_algorithm="SPRAY_TO_REGION",
auto_capacity_drain={
"enable": True,
},
failover_config={
"failover_health_threshold": 70,
},
isolation_config={
"isolation_granularity": "REGION",
"isolation_mode": "NEAREST",
},
labels={
"foo": "bar",
})
default_backend_service = gcp.compute.BackendService("default",
name="my-lb-backend",
description="my description",
load_balancing_scheme="INTERNAL_SELF_MANAGED",
protocol="HTTP",
service_lb_policy=default.id.apply(lambda id: f"//networkservices.googleapis.com/{id}"))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/networkservices"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_default, err := networkservices.NewServiceLbPolicies(ctx, "default", &networkservices.ServiceLbPoliciesArgs{
Name: pulumi.String("my-lb-policy"),
Location: pulumi.String("global"),
Description: pulumi.String("my description"),
LoadBalancingAlgorithm: pulumi.String("SPRAY_TO_REGION"),
AutoCapacityDrain: &networkservices.ServiceLbPoliciesAutoCapacityDrainArgs{
Enable: pulumi.Bool(true),
},
FailoverConfig: &networkservices.ServiceLbPoliciesFailoverConfigArgs{
FailoverHealthThreshold: pulumi.Int(70),
},
IsolationConfig: &networkservices.ServiceLbPoliciesIsolationConfigArgs{
IsolationGranularity: pulumi.String("REGION"),
IsolationMode: pulumi.String("NEAREST"),
},
Labels: pulumi.StringMap{
"foo": pulumi.String("bar"),
},
})
if err != nil {
return err
}
_, err = compute.NewBackendService(ctx, "default", &compute.BackendServiceArgs{
Name: pulumi.String("my-lb-backend"),
Description: pulumi.String("my description"),
LoadBalancingScheme: pulumi.String("INTERNAL_SELF_MANAGED"),
Protocol: pulumi.String("HTTP"),
ServiceLbPolicy: _default.ID().ApplyT(func(id string) (string, error) {
return fmt.Sprintf("//networkservices.googleapis.com/%v", id), nil
}).(pulumi.StringOutput),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var @default = new Gcp.NetworkServices.ServiceLbPolicies("default", new()
{
Name = "my-lb-policy",
Location = "global",
Description = "my description",
LoadBalancingAlgorithm = "SPRAY_TO_REGION",
AutoCapacityDrain = new Gcp.NetworkServices.Inputs.ServiceLbPoliciesAutoCapacityDrainArgs
{
Enable = true,
},
FailoverConfig = new Gcp.NetworkServices.Inputs.ServiceLbPoliciesFailoverConfigArgs
{
FailoverHealthThreshold = 70,
},
IsolationConfig = new Gcp.NetworkServices.Inputs.ServiceLbPoliciesIsolationConfigArgs
{
IsolationGranularity = "REGION",
IsolationMode = "NEAREST",
},
Labels =
{
{ "foo", "bar" },
},
});
var defaultBackendService = new Gcp.Compute.BackendService("default", new()
{
Name = "my-lb-backend",
Description = "my description",
LoadBalancingScheme = "INTERNAL_SELF_MANAGED",
Protocol = "HTTP",
ServiceLbPolicy = @default.Id.Apply(id => $"//networkservices.googleapis.com/{id}"),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.networkservices.ServiceLbPolicies;
import com.pulumi.gcp.networkservices.ServiceLbPoliciesArgs;
import com.pulumi.gcp.networkservices.inputs.ServiceLbPoliciesAutoCapacityDrainArgs;
import com.pulumi.gcp.networkservices.inputs.ServiceLbPoliciesFailoverConfigArgs;
import com.pulumi.gcp.networkservices.inputs.ServiceLbPoliciesIsolationConfigArgs;
import com.pulumi.gcp.compute.BackendService;
import com.pulumi.gcp.compute.BackendServiceArgs;
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 default_ = new ServiceLbPolicies("default", ServiceLbPoliciesArgs.builder()
.name("my-lb-policy")
.location("global")
.description("my description")
.loadBalancingAlgorithm("SPRAY_TO_REGION")
.autoCapacityDrain(ServiceLbPoliciesAutoCapacityDrainArgs.builder()
.enable(true)
.build())
.failoverConfig(ServiceLbPoliciesFailoverConfigArgs.builder()
.failoverHealthThreshold(70)
.build())
.isolationConfig(ServiceLbPoliciesIsolationConfigArgs.builder()
.isolationGranularity("REGION")
.isolationMode("NEAREST")
.build())
.labels(Map.of("foo", "bar"))
.build());
var defaultBackendService = new BackendService("defaultBackendService", BackendServiceArgs.builder()
.name("my-lb-backend")
.description("my description")
.loadBalancingScheme("INTERNAL_SELF_MANAGED")
.protocol("HTTP")
.serviceLbPolicy(default_.id().applyValue(_id -> String.format("//networkservices.googleapis.com/%s", _id)))
.build());
}
}
resources:
default:
type: gcp:networkservices:ServiceLbPolicies
properties:
name: my-lb-policy
location: global
description: my description
loadBalancingAlgorithm: SPRAY_TO_REGION
autoCapacityDrain:
enable: true
failoverConfig:
failoverHealthThreshold: 70
isolationConfig:
isolationGranularity: REGION
isolationMode: NEAREST
labels:
foo: bar
defaultBackendService:
type: gcp:compute:BackendService
name: default
properties:
name: my-lb-backend
description: my description
loadBalancingScheme: INTERNAL_SELF_MANAGED
protocol: HTTP
serviceLbPolicy: //networkservices.googleapis.com/${default.id}
The isolationConfig block adds geographic traffic boundaries. The isolationGranularity property sets the boundary level (REGION keeps traffic within regional boundaries), while isolationMode determines routing behavior (NEAREST routes to the closest available backend within the isolation boundary). This configuration extends the previous example’s traffic distribution and failover settings with an additional isolation layer.
Beyond these examples
These snippets focus on specific policy-level features: traffic distribution algorithms, capacity draining and failover, and regional isolation controls. They’re intentionally minimal rather than full load balancing configurations.
The examples may reference pre-existing infrastructure such as GCP projects with Network Services API enabled and backend services to attach policies to. They focus on configuring the policy rather than provisioning the complete load balancing stack.
To keep things focused, common policy patterns are omitted, including:
- Policy attachment to multiple backend services
- Custom health check thresholds beyond failover
- Integration with Cloud Armor security policies
- Monitoring and observability configuration
These omissions are intentional: the goal is to illustrate how each policy feature is wired, not provide drop-in load balancing modules. See the ServiceLbPolicies resource reference for all available configuration options.
Let's configure GCP Service Load Balancing Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Setup
serviceLbPolicy property to the policy’s ID using the format //networkservices.googleapis.com/${policyId}, as shown in the advanced example.location property is required. Examples in the schema use global for global load balancing policies.SPRAY_TO_REGION, SPRAY_TO_WORLD, WATERFALL_BY_REGION (default), and WATERFALL_BY_ZONE.Labels & Metadata
labels field is non-authoritative and only manages labels in your configuration. Use effectiveLabels to access all labels present on the resource in GCP, including those configured through other clients and services.Advanced Features
failoverConfig property provides health-based failover behavior for ServiceLbPolicy and is NOT related to Network Load Balancer FailoverPolicy. They are separate features.autoCapacityDrain option specifies whether an unhealthy MIG (Managed Instance Group) or NEG (Network Endpoint Group) should be considered for global load balancing and traffic routing.isolationConfig property provides isolation support for the associated Backend Service. It’s shown in the beta example with isolationGranularity and isolationMode settings.Resource Management
project property is immutable. Changing it after creation forces resource replacement.Using a different cloud?
Explore networking guides for other cloud providers: