Configure GCP Public Delegated Prefixes

The gcp:compute/publicDelegatedPrefix:PublicDelegatedPrefix resource, part of the Pulumi GCP provider, defines delegated IP prefixes that carve smaller subnets from your BYOIP (bring your own IP) ranges for regional use. This guide focuses on three capabilities: IPv4 prefix delegation, IPv6 hierarchical delegation with mode configuration, and subnet and forwarding rule allocation patterns.

Delegated prefixes depend on a parent PublicAdvertisedPrefix that represents your onboarded BYOIP range. The examples are intentionally small. Combine them with your own VPC subnets, forwarding rules, and network architecture.

Delegate an IPv4 prefix from an advertised range

Organizations bringing their own IPv4 addresses to GCP start by advertising a prefix, then delegating smaller regional subnets from it.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const advertised = new gcp.compute.PublicAdvertisedPrefix("advertised", {
    name: "my-prefix",
    description: "description",
    dnsVerificationIp: "127.127.0.0",
    ipCidrRange: "127.127.0.0/16",
});
const prefixes = new gcp.compute.PublicDelegatedPrefix("prefixes", {
    name: "my-prefix",
    region: "us-central1",
    description: "my description",
    ipCidrRange: "127.127.0.0/24",
    parentPrefix: advertised.id,
});
import pulumi
import pulumi_gcp as gcp

advertised = gcp.compute.PublicAdvertisedPrefix("advertised",
    name="my-prefix",
    description="description",
    dns_verification_ip="127.127.0.0",
    ip_cidr_range="127.127.0.0/16")
prefixes = gcp.compute.PublicDelegatedPrefix("prefixes",
    name="my-prefix",
    region="us-central1",
    description="my description",
    ip_cidr_range="127.127.0.0/24",
    parent_prefix=advertised.id)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		advertised, err := compute.NewPublicAdvertisedPrefix(ctx, "advertised", &compute.PublicAdvertisedPrefixArgs{
			Name:              pulumi.String("my-prefix"),
			Description:       pulumi.String("description"),
			DnsVerificationIp: pulumi.String("127.127.0.0"),
			IpCidrRange:       pulumi.String("127.127.0.0/16"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewPublicDelegatedPrefix(ctx, "prefixes", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("my-prefix"),
			Region:       pulumi.String("us-central1"),
			Description:  pulumi.String("my description"),
			IpCidrRange:  pulumi.String("127.127.0.0/24"),
			ParentPrefix: advertised.ID(),
		})
		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 advertised = new Gcp.Compute.PublicAdvertisedPrefix("advertised", new()
    {
        Name = "my-prefix",
        Description = "description",
        DnsVerificationIp = "127.127.0.0",
        IpCidrRange = "127.127.0.0/16",
    });

    var prefixes = new Gcp.Compute.PublicDelegatedPrefix("prefixes", new()
    {
        Name = "my-prefix",
        Region = "us-central1",
        Description = "my description",
        IpCidrRange = "127.127.0.0/24",
        ParentPrefix = advertised.Id,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
import com.pulumi.gcp.compute.PublicDelegatedPrefix;
import com.pulumi.gcp.compute.PublicDelegatedPrefixArgs;
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 advertised = new PublicAdvertisedPrefix("advertised", PublicAdvertisedPrefixArgs.builder()
            .name("my-prefix")
            .description("description")
            .dnsVerificationIp("127.127.0.0")
            .ipCidrRange("127.127.0.0/16")
            .build());

        var prefixes = new PublicDelegatedPrefix("prefixes", PublicDelegatedPrefixArgs.builder()
            .name("my-prefix")
            .region("us-central1")
            .description("my description")
            .ipCidrRange("127.127.0.0/24")
            .parentPrefix(advertised.id())
            .build());

    }
}
resources:
  advertised:
    type: gcp:compute:PublicAdvertisedPrefix
    properties:
      name: my-prefix
      description: description
      dnsVerificationIp: 127.127.0.0
      ipCidrRange: 127.127.0.0/16
  prefixes:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: my-prefix
      region: us-central1
      description: my description
      ipCidrRange: 127.127.0.0/24
      parentPrefix: ${advertised.id}

The parentPrefix property links this delegated prefix to your advertised BYOIP range. The ipCidrRange carves out a smaller subnet (here /24 from a /16 parent) that can be used in the specified region. IPv4 prefixes don’t require a mode property; they default to basic delegation behavior.

Create a hierarchy for IPv6 forwarding rules

IPv6 BYOIP requires a two-level delegation hierarchy: a root prefix in DELEGATION mode, then sub-prefixes that allocate addresses for forwarding rules.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const advertised = new gcp.compute.PublicAdvertisedPrefix("advertised", {
    name: "ipv6-pap",
    description: "description",
    dnsVerificationIp: "2001:db8::",
    ipCidrRange: "2001:db8::/32",
    pdpScope: "REGIONAL",
});
const prefix = new gcp.compute.PublicDelegatedPrefix("prefix", {
    name: "ipv6-root-pdp",
    description: "test-delegation-mode-pdp",
    region: "us-west1",
    ipCidrRange: "2001:db8::/40",
    parentPrefix: advertised.id,
    mode: "DELEGATION",
});
const subprefix = new gcp.compute.PublicDelegatedPrefix("subprefix", {
    name: "ipv6-sub-pdp",
    description: "test-forwarding-rule-mode-pdp",
    region: "us-west1",
    ipCidrRange: "2001:db8::/48",
    parentPrefix: prefix.id,
    allocatablePrefixLength: 64,
    mode: "EXTERNAL_IPV6_FORWARDING_RULE_CREATION",
});
import pulumi
import pulumi_gcp as gcp

advertised = gcp.compute.PublicAdvertisedPrefix("advertised",
    name="ipv6-pap",
    description="description",
    dns_verification_ip="2001:db8::",
    ip_cidr_range="2001:db8::/32",
    pdp_scope="REGIONAL")
prefix = gcp.compute.PublicDelegatedPrefix("prefix",
    name="ipv6-root-pdp",
    description="test-delegation-mode-pdp",
    region="us-west1",
    ip_cidr_range="2001:db8::/40",
    parent_prefix=advertised.id,
    mode="DELEGATION")
subprefix = gcp.compute.PublicDelegatedPrefix("subprefix",
    name="ipv6-sub-pdp",
    description="test-forwarding-rule-mode-pdp",
    region="us-west1",
    ip_cidr_range="2001:db8::/48",
    parent_prefix=prefix.id,
    allocatable_prefix_length=64,
    mode="EXTERNAL_IPV6_FORWARDING_RULE_CREATION")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		advertised, err := compute.NewPublicAdvertisedPrefix(ctx, "advertised", &compute.PublicAdvertisedPrefixArgs{
			Name:              pulumi.String("ipv6-pap"),
			Description:       pulumi.String("description"),
			DnsVerificationIp: pulumi.String("2001:db8::"),
			IpCidrRange:       pulumi.String("2001:db8::/32"),
			PdpScope:          pulumi.String("REGIONAL"),
		})
		if err != nil {
			return err
		}
		prefix, err := compute.NewPublicDelegatedPrefix(ctx, "prefix", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("ipv6-root-pdp"),
			Description:  pulumi.String("test-delegation-mode-pdp"),
			Region:       pulumi.String("us-west1"),
			IpCidrRange:  pulumi.String("2001:db8::/40"),
			ParentPrefix: advertised.ID(),
			Mode:         pulumi.String("DELEGATION"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewPublicDelegatedPrefix(ctx, "subprefix", &compute.PublicDelegatedPrefixArgs{
			Name:                    pulumi.String("ipv6-sub-pdp"),
			Description:             pulumi.String("test-forwarding-rule-mode-pdp"),
			Region:                  pulumi.String("us-west1"),
			IpCidrRange:             pulumi.String("2001:db8::/48"),
			ParentPrefix:            prefix.ID(),
			AllocatablePrefixLength: pulumi.Int(64),
			Mode:                    pulumi.String("EXTERNAL_IPV6_FORWARDING_RULE_CREATION"),
		})
		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 advertised = new Gcp.Compute.PublicAdvertisedPrefix("advertised", new()
    {
        Name = "ipv6-pap",
        Description = "description",
        DnsVerificationIp = "2001:db8::",
        IpCidrRange = "2001:db8::/32",
        PdpScope = "REGIONAL",
    });

    var prefix = new Gcp.Compute.PublicDelegatedPrefix("prefix", new()
    {
        Name = "ipv6-root-pdp",
        Description = "test-delegation-mode-pdp",
        Region = "us-west1",
        IpCidrRange = "2001:db8::/40",
        ParentPrefix = advertised.Id,
        Mode = "DELEGATION",
    });

    var subprefix = new Gcp.Compute.PublicDelegatedPrefix("subprefix", new()
    {
        Name = "ipv6-sub-pdp",
        Description = "test-forwarding-rule-mode-pdp",
        Region = "us-west1",
        IpCidrRange = "2001:db8::/48",
        ParentPrefix = prefix.Id,
        AllocatablePrefixLength = 64,
        Mode = "EXTERNAL_IPV6_FORWARDING_RULE_CREATION",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
import com.pulumi.gcp.compute.PublicDelegatedPrefix;
import com.pulumi.gcp.compute.PublicDelegatedPrefixArgs;
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 advertised = new PublicAdvertisedPrefix("advertised", PublicAdvertisedPrefixArgs.builder()
            .name("ipv6-pap")
            .description("description")
            .dnsVerificationIp("2001:db8::")
            .ipCidrRange("2001:db8::/32")
            .pdpScope("REGIONAL")
            .build());

        var prefix = new PublicDelegatedPrefix("prefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-root-pdp")
            .description("test-delegation-mode-pdp")
            .region("us-west1")
            .ipCidrRange("2001:db8::/40")
            .parentPrefix(advertised.id())
            .mode("DELEGATION")
            .build());

        var subprefix = new PublicDelegatedPrefix("subprefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-sub-pdp")
            .description("test-forwarding-rule-mode-pdp")
            .region("us-west1")
            .ipCidrRange("2001:db8::/48")
            .parentPrefix(prefix.id())
            .allocatablePrefixLength(64)
            .mode("EXTERNAL_IPV6_FORWARDING_RULE_CREATION")
            .build());

    }
}
resources:
  advertised:
    type: gcp:compute:PublicAdvertisedPrefix
    properties:
      name: ipv6-pap
      description: description
      dnsVerificationIp: '2001:db8::'
      ipCidrRange: 2001:db8::/32
      pdpScope: REGIONAL
  prefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-root-pdp
      description: test-delegation-mode-pdp
      region: us-west1
      ipCidrRange: 2001:db8::/40
      parentPrefix: ${advertised.id}
      mode: DELEGATION
  subprefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-sub-pdp
      description: test-forwarding-rule-mode-pdp
      region: us-west1
      ipCidrRange: 2001:db8::/48
      parentPrefix: ${prefix.id}
      allocatablePrefixLength: 64
      mode: EXTERNAL_IPV6_FORWARDING_RULE_CREATION

The mode property controls how addresses are allocated. The root prefix uses DELEGATION mode to enable further subdivision. The sub-prefix uses EXTERNAL_IPV6_FORWARDING_RULE_CREATION mode, which allows load balancers and forwarding rules to claim addresses. The allocatablePrefixLength (64) sets the size of individual address allocations.

Allocate IPv6 ranges for VPC subnets

VPC subnets can use IPv6 addresses from your BYOIP range when you configure a sub-prefix in subnet creation mode.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const advertised = new gcp.compute.PublicAdvertisedPrefix("advertised", {
    name: "ipv6-pap",
    description: "description",
    dnsVerificationIp: "2001:db8::",
    ipCidrRange: "2001:db8::/32",
    pdpScope: "REGIONAL",
});
const prefix = new gcp.compute.PublicDelegatedPrefix("prefix", {
    name: "ipv6-root-pdp",
    description: "test-delegation-mode-pdp",
    region: "us-east1",
    ipCidrRange: "2001:db8::/40",
    parentPrefix: advertised.id,
    mode: "DELEGATION",
});
const subprefix = new gcp.compute.PublicDelegatedPrefix("subprefix", {
    name: "ipv6-sub-pdp",
    description: "test-subnet-mode-pdp",
    region: "us-east1",
    ipCidrRange: "2001:db8::/48",
    parentPrefix: prefix.id,
    mode: "EXTERNAL_IPV6_SUBNETWORK_CREATION",
});
import pulumi
import pulumi_gcp as gcp

advertised = gcp.compute.PublicAdvertisedPrefix("advertised",
    name="ipv6-pap",
    description="description",
    dns_verification_ip="2001:db8::",
    ip_cidr_range="2001:db8::/32",
    pdp_scope="REGIONAL")
prefix = gcp.compute.PublicDelegatedPrefix("prefix",
    name="ipv6-root-pdp",
    description="test-delegation-mode-pdp",
    region="us-east1",
    ip_cidr_range="2001:db8::/40",
    parent_prefix=advertised.id,
    mode="DELEGATION")
subprefix = gcp.compute.PublicDelegatedPrefix("subprefix",
    name="ipv6-sub-pdp",
    description="test-subnet-mode-pdp",
    region="us-east1",
    ip_cidr_range="2001:db8::/48",
    parent_prefix=prefix.id,
    mode="EXTERNAL_IPV6_SUBNETWORK_CREATION")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		advertised, err := compute.NewPublicAdvertisedPrefix(ctx, "advertised", &compute.PublicAdvertisedPrefixArgs{
			Name:              pulumi.String("ipv6-pap"),
			Description:       pulumi.String("description"),
			DnsVerificationIp: pulumi.String("2001:db8::"),
			IpCidrRange:       pulumi.String("2001:db8::/32"),
			PdpScope:          pulumi.String("REGIONAL"),
		})
		if err != nil {
			return err
		}
		prefix, err := compute.NewPublicDelegatedPrefix(ctx, "prefix", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("ipv6-root-pdp"),
			Description:  pulumi.String("test-delegation-mode-pdp"),
			Region:       pulumi.String("us-east1"),
			IpCidrRange:  pulumi.String("2001:db8::/40"),
			ParentPrefix: advertised.ID(),
			Mode:         pulumi.String("DELEGATION"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewPublicDelegatedPrefix(ctx, "subprefix", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("ipv6-sub-pdp"),
			Description:  pulumi.String("test-subnet-mode-pdp"),
			Region:       pulumi.String("us-east1"),
			IpCidrRange:  pulumi.String("2001:db8::/48"),
			ParentPrefix: prefix.ID(),
			Mode:         pulumi.String("EXTERNAL_IPV6_SUBNETWORK_CREATION"),
		})
		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 advertised = new Gcp.Compute.PublicAdvertisedPrefix("advertised", new()
    {
        Name = "ipv6-pap",
        Description = "description",
        DnsVerificationIp = "2001:db8::",
        IpCidrRange = "2001:db8::/32",
        PdpScope = "REGIONAL",
    });

    var prefix = new Gcp.Compute.PublicDelegatedPrefix("prefix", new()
    {
        Name = "ipv6-root-pdp",
        Description = "test-delegation-mode-pdp",
        Region = "us-east1",
        IpCidrRange = "2001:db8::/40",
        ParentPrefix = advertised.Id,
        Mode = "DELEGATION",
    });

    var subprefix = new Gcp.Compute.PublicDelegatedPrefix("subprefix", new()
    {
        Name = "ipv6-sub-pdp",
        Description = "test-subnet-mode-pdp",
        Region = "us-east1",
        IpCidrRange = "2001:db8::/48",
        ParentPrefix = prefix.Id,
        Mode = "EXTERNAL_IPV6_SUBNETWORK_CREATION",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
import com.pulumi.gcp.compute.PublicDelegatedPrefix;
import com.pulumi.gcp.compute.PublicDelegatedPrefixArgs;
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 advertised = new PublicAdvertisedPrefix("advertised", PublicAdvertisedPrefixArgs.builder()
            .name("ipv6-pap")
            .description("description")
            .dnsVerificationIp("2001:db8::")
            .ipCidrRange("2001:db8::/32")
            .pdpScope("REGIONAL")
            .build());

        var prefix = new PublicDelegatedPrefix("prefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-root-pdp")
            .description("test-delegation-mode-pdp")
            .region("us-east1")
            .ipCidrRange("2001:db8::/40")
            .parentPrefix(advertised.id())
            .mode("DELEGATION")
            .build());

        var subprefix = new PublicDelegatedPrefix("subprefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-sub-pdp")
            .description("test-subnet-mode-pdp")
            .region("us-east1")
            .ipCidrRange("2001:db8::/48")
            .parentPrefix(prefix.id())
            .mode("EXTERNAL_IPV6_SUBNETWORK_CREATION")
            .build());

    }
}
resources:
  advertised:
    type: gcp:compute:PublicAdvertisedPrefix
    properties:
      name: ipv6-pap
      description: description
      dnsVerificationIp: '2001:db8::'
      ipCidrRange: 2001:db8::/32
      pdpScope: REGIONAL
  prefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-root-pdp
      description: test-delegation-mode-pdp
      region: us-east1
      ipCidrRange: 2001:db8::/40
      parentPrefix: ${advertised.id}
      mode: DELEGATION
  subprefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-sub-pdp
      description: test-subnet-mode-pdp
      region: us-east1
      ipCidrRange: 2001:db8::/48
      parentPrefix: ${prefix.id}
      mode: EXTERNAL_IPV6_SUBNETWORK_CREATION

This configuration mirrors the forwarding rule example but uses EXTERNAL_IPV6_SUBNETWORK_CREATION mode instead. This mode allows VPC subnets to claim IPv6 ranges from the delegated prefix. The two-level hierarchy (root in DELEGATION mode, sub-prefix in subnet mode) is required for IPv6.

Configure internal IPv6 ranges for private subnets

Some deployments need IPv6 addresses that remain internal to Google Cloud without internet announcement.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const advertised = new gcp.compute.PublicAdvertisedPrefix("advertised", {
    name: "ipv6-pap",
    description: "description",
    ipCidrRange: "2001:db8::/32",
    pdpScope: "REGIONAL",
    ipv6AccessType: "INTERNAL",
});
const prefix = new gcp.compute.PublicDelegatedPrefix("prefix", {
    name: "ipv6-root-pdp",
    description: "test-delegation-mode-pdp",
    region: "us-east1",
    ipCidrRange: "2001:db8::/40",
    parentPrefix: advertised.id,
    mode: "DELEGATION",
});
const subprefix = new gcp.compute.PublicDelegatedPrefix("subprefix", {
    name: "ipv6-sub-pdp",
    description: "test-subnet-mode-pdp",
    region: "us-east1",
    ipCidrRange: "2001:db8::/48",
    parentPrefix: prefix.id,
    mode: "INTERNAL_IPV6_SUBNETWORK_CREATION",
});
import pulumi
import pulumi_gcp as gcp

advertised = gcp.compute.PublicAdvertisedPrefix("advertised",
    name="ipv6-pap",
    description="description",
    ip_cidr_range="2001:db8::/32",
    pdp_scope="REGIONAL",
    ipv6_access_type="INTERNAL")
prefix = gcp.compute.PublicDelegatedPrefix("prefix",
    name="ipv6-root-pdp",
    description="test-delegation-mode-pdp",
    region="us-east1",
    ip_cidr_range="2001:db8::/40",
    parent_prefix=advertised.id,
    mode="DELEGATION")
subprefix = gcp.compute.PublicDelegatedPrefix("subprefix",
    name="ipv6-sub-pdp",
    description="test-subnet-mode-pdp",
    region="us-east1",
    ip_cidr_range="2001:db8::/48",
    parent_prefix=prefix.id,
    mode="INTERNAL_IPV6_SUBNETWORK_CREATION")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		advertised, err := compute.NewPublicAdvertisedPrefix(ctx, "advertised", &compute.PublicAdvertisedPrefixArgs{
			Name:           pulumi.String("ipv6-pap"),
			Description:    pulumi.String("description"),
			IpCidrRange:    pulumi.String("2001:db8::/32"),
			PdpScope:       pulumi.String("REGIONAL"),
			Ipv6AccessType: pulumi.String("INTERNAL"),
		})
		if err != nil {
			return err
		}
		prefix, err := compute.NewPublicDelegatedPrefix(ctx, "prefix", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("ipv6-root-pdp"),
			Description:  pulumi.String("test-delegation-mode-pdp"),
			Region:       pulumi.String("us-east1"),
			IpCidrRange:  pulumi.String("2001:db8::/40"),
			ParentPrefix: advertised.ID(),
			Mode:         pulumi.String("DELEGATION"),
		})
		if err != nil {
			return err
		}
		_, err = compute.NewPublicDelegatedPrefix(ctx, "subprefix", &compute.PublicDelegatedPrefixArgs{
			Name:         pulumi.String("ipv6-sub-pdp"),
			Description:  pulumi.String("test-subnet-mode-pdp"),
			Region:       pulumi.String("us-east1"),
			IpCidrRange:  pulumi.String("2001:db8::/48"),
			ParentPrefix: prefix.ID(),
			Mode:         pulumi.String("INTERNAL_IPV6_SUBNETWORK_CREATION"),
		})
		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 advertised = new Gcp.Compute.PublicAdvertisedPrefix("advertised", new()
    {
        Name = "ipv6-pap",
        Description = "description",
        IpCidrRange = "2001:db8::/32",
        PdpScope = "REGIONAL",
        Ipv6AccessType = "INTERNAL",
    });

    var prefix = new Gcp.Compute.PublicDelegatedPrefix("prefix", new()
    {
        Name = "ipv6-root-pdp",
        Description = "test-delegation-mode-pdp",
        Region = "us-east1",
        IpCidrRange = "2001:db8::/40",
        ParentPrefix = advertised.Id,
        Mode = "DELEGATION",
    });

    var subprefix = new Gcp.Compute.PublicDelegatedPrefix("subprefix", new()
    {
        Name = "ipv6-sub-pdp",
        Description = "test-subnet-mode-pdp",
        Region = "us-east1",
        IpCidrRange = "2001:db8::/48",
        ParentPrefix = prefix.Id,
        Mode = "INTERNAL_IPV6_SUBNETWORK_CREATION",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.PublicAdvertisedPrefix;
import com.pulumi.gcp.compute.PublicAdvertisedPrefixArgs;
import com.pulumi.gcp.compute.PublicDelegatedPrefix;
import com.pulumi.gcp.compute.PublicDelegatedPrefixArgs;
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 advertised = new PublicAdvertisedPrefix("advertised", PublicAdvertisedPrefixArgs.builder()
            .name("ipv6-pap")
            .description("description")
            .ipCidrRange("2001:db8::/32")
            .pdpScope("REGIONAL")
            .ipv6AccessType("INTERNAL")
            .build());

        var prefix = new PublicDelegatedPrefix("prefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-root-pdp")
            .description("test-delegation-mode-pdp")
            .region("us-east1")
            .ipCidrRange("2001:db8::/40")
            .parentPrefix(advertised.id())
            .mode("DELEGATION")
            .build());

        var subprefix = new PublicDelegatedPrefix("subprefix", PublicDelegatedPrefixArgs.builder()
            .name("ipv6-sub-pdp")
            .description("test-subnet-mode-pdp")
            .region("us-east1")
            .ipCidrRange("2001:db8::/48")
            .parentPrefix(prefix.id())
            .mode("INTERNAL_IPV6_SUBNETWORK_CREATION")
            .build());

    }
}
resources:
  advertised:
    type: gcp:compute:PublicAdvertisedPrefix
    properties:
      name: ipv6-pap
      description: description
      ipCidrRange: 2001:db8::/32
      pdpScope: REGIONAL
      ipv6AccessType: INTERNAL
  prefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-root-pdp
      description: test-delegation-mode-pdp
      region: us-east1
      ipCidrRange: 2001:db8::/40
      parentPrefix: ${advertised.id}
      mode: DELEGATION
  subprefix:
    type: gcp:compute:PublicDelegatedPrefix
    properties:
      name: ipv6-sub-pdp
      description: test-subnet-mode-pdp
      region: us-east1
      ipCidrRange: 2001:db8::/48
      parentPrefix: ${prefix.id}
      mode: INTERNAL_IPV6_SUBNETWORK_CREATION

The INTERNAL_IPV6_SUBNETWORK_CREATION mode creates prefixes for internal-only subnets. The parent PublicAdvertisedPrefix must have ipv6AccessType set to INTERNAL, which prevents the range from being announced to the internet. The ipv6AccessType output property is inherited from the parent and confirms the access level.

Beyond these examples

These snippets focus on specific prefix delegation features: IPv4 and IPv6 prefix delegation, mode configuration for different allocation patterns, and hierarchical prefix relationships. They’re intentionally minimal rather than full network deployments.

The examples require pre-existing infrastructure such as PublicAdvertisedPrefix resources (BYOIP onboarding), DNS verification for IPv4 ranges, and regional scope configuration for IPv6. They focus on prefix configuration rather than the complete BYOIP onboarding process.

To keep things focused, common prefix patterns are omitted, including:

  • Live migration configuration (isLiveMigration)
  • Actual subnet or forwarding rule creation using delegated prefixes
  • Multi-region prefix distribution
  • Prefix lifecycle management and deletion

These omissions are intentional: the goal is to illustrate how prefix delegation is wired, not provide drop-in BYOIP modules. See the PublicDelegatedPrefix resource reference for all available configuration options.

Let's configure GCP Public Delegated Prefixes

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
What properties are immutable after creation?
Nearly all properties are immutable, including ipCidrRange, name, parentPrefix, region, mode, description, allocatablePrefixLength, and isLiveMigration. Changing any of these requires destroying and recreating the resource.
What naming requirements must my prefix follow?
The name must be 1-63 characters long and comply with RFC1035: start with a lowercase letter, followed by dashes, lowercase letters, or digits, and cannot end with a dash.
Modes & Use Cases
What are the different mode values and when should I use each?

There are four modes for IPv6 prefixes:

  1. DELEGATION - For creating sub-prefixes that can be further delegated
  2. EXTERNAL_IPV6_FORWARDING_RULE_CREATION - For creating forwarding rules
  3. EXTERNAL_IPV6_SUBNETWORK_CREATION - For creating external IPv6 subnets
  4. INTERNAL_IPV6_SUBNETWORK_CREATION - For creating internal IPv6 subnets
When should I use DELEGATION mode versus other modes?
Use DELEGATION mode when you want to create a root prefix that can be subdivided into smaller prefixes. Use the other modes (FORWARDING_RULE_CREATION, SUBNETWORK_CREATION) for leaf prefixes that will be directly used for resources.
Prefix Hierarchy & Relationships
How do I create a hierarchy of delegated prefixes?
Create a PublicAdvertisedPrefix first, then create a root PublicDelegatedPrefix with mode set to DELEGATION referencing the advertised prefix, then create sub-prefixes referencing the root prefix with appropriate modes.
What can I use as a parent prefix?
The parentPrefix can be either a PublicAdvertisedPrefix or another PublicDelegatedPrefix, allowing you to create hierarchical prefix structures.
IPv6-Specific Features
When should I set allocatablePrefixLength?
Set allocatablePrefixLength only for IPv6 prefixes in EXTERNAL_IPV6_FORWARDING_RULE_CREATION mode. It cannot be set for DELEGATION mode or IPv4 prefixes (IPv4 always defaults to 32).
What does ipv6AccessType control and how is it set?
The ipv6AccessType is an output-only field inherited from the parent prefix. EXTERNAL means the prefix is announced to the internet, while INTERNAL means it’s used privately within Google Cloud. Set this on the parent PublicAdvertisedPrefix.
Can I use PublicDelegatedPrefix for IPv4 addresses?
Yes, the basic example shows IPv4 usage with CIDR range 127.127.0.0/24. However, IPv4 prefixes don’t support the mode or allocatablePrefixLength properties (allocatablePrefixLength always defaults to 32 for IPv4).

Using a different cloud?

Explore networking guides for other cloud providers: