Configure GCP Service Load Balancing Policies

The gcp:networkservices/serviceLbPolicies:ServiceLbPolicies resource, part of the Pulumi GCP provider, defines global load balancing and traffic distribution policies that control how traffic flows to backend services. This guide focuses on three capabilities: traffic distribution algorithms, health-based failover configuration, and regional isolation controls.

Policies are attached to BackendService resources via the serviceLbPolicy property. The examples are intentionally small. Combine them with your own backend services and health checks.

Create a minimal 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 Mesh policies. Without additional configuration, the policy uses default behavior (WATERFALL_BY_REGION algorithm) and can be attached to backend services.

Configure traffic distribution and failover behavior

Production deployments need control over how traffic spreads across regions and how the system responds to unhealthy backends.

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 determines traffic distribution: SPRAY_TO_REGION spreads requests across all healthy regions, while WATERFALL_BY_REGION prefers closer regions first. The autoCapacityDrain block tells the load balancer to automatically stop sending traffic to unhealthy managed instance groups or network endpoint groups. The failoverConfig sets a health threshold (70%) that triggers failover to backup regions. The BackendService resource references the policy using an interpolated ID that includes the full resource path.

Add isolation controls for regional traffic containment

Applications with data residency requirements can use isolation configuration to control cross-region traffic.

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 regional boundaries to traffic distribution. The isolationGranularity property sets whether isolation applies at the REGION level, and isolationMode determines the fallback behavior: NEAREST keeps traffic in the closest healthy region before failing over. This extends the traffic distribution and failover configuration with an additional containment layer.

Beyond these examples

These snippets focus on specific policy-level features: traffic distribution algorithms, health-based failover and capacity draining, 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 failoverHealthThreshold
  • Integration with service mesh routing rules
  • Policy versioning and rollback strategies

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 FREE

Frequently Asked Questions

Provider & Setup
Do I need a special provider to use ServiceLbPolicy?
Yes, this is a beta resource that requires the terraform-provider-google-beta provider.
What location should I use for my ServiceLbPolicy?
Use global as the location, as shown in all the examples.
Configuration & Algorithms
What load balancing algorithms are available?
Four algorithms are available: SPRAY_TO_REGION, SPRAY_TO_WORLD, WATERFALL_BY_REGION (default), and WATERFALL_BY_ZONE.
Is failoverConfig the same as Network Load Balancer's FailoverPolicy?
No, failoverConfig provides health-based failover behavior and is not related to Network Load Balancer FailoverPolicy.
Integration & Usage
How do I attach a ServiceLbPolicy to a BackendService?
Set the BackendService’s serviceLbPolicy property to the policy’s ID using the format //networkservices.googleapis.com/${policyId}.
Resource Management
Can I change the project after creating a ServiceLbPolicy?
No, the project property is immutable and cannot be changed after creation.
Why should I use effectiveLabels instead of labels?
The labels field is non-authoritative and only manages labels in your configuration. Use effectiveLabels to see all labels present on the resource, including those set by other clients and services.

Using a different cloud?

Explore networking guides for other cloud providers: