Configure GCP Public Delegated Prefixes

The gcp:compute/publicDelegatedPrefix:PublicDelegatedPrefix resource, part of the Pulumi GCP provider, defines delegated IP prefixes within BYOIP ranges, controlling how addresses are allocated for forwarding rules, subnets, or further delegation. This guide focuses on three capabilities: IPv4 and IPv6 prefix delegation, hierarchical prefix structures, and mode-based allocation strategies.

Delegated prefixes depend on a PublicAdvertisedPrefix (the parent BYOIP range) that has completed DNS verification and advertisement. 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 its advertised parent. The ipCidrRange must be a subset of the parent’s range. The region property determines where this prefix can be used for address allocation.

Create a hierarchy for IPv6 forwarding rules

IPv6 BYOIP deployments often require multiple delegation levels: a root prefix delegates to regional prefixes, which then allocate addresses for load balancers.

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

This example creates a three-tier hierarchy. The root prefix uses mode DELEGATION to allow further subdivision. The subprefix uses mode EXTERNAL_IPV6_FORWARDING_RULE_CREATION to enable address allocation for forwarding rules. The allocatablePrefixLength property (64) determines the size of addresses that can be allocated from this prefix.

Allocate IPv6 prefixes for subnet creation

VPC subnets can use IPv6 addresses from BYOIP ranges when the delegated prefix is configured for subnet creation.

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

The mode EXTERNAL_IPV6_SUBNETWORK_CREATION allows VPC subnets to allocate IPv6 ranges from this prefix. This differs from forwarding rule mode: subnets receive entire IPv6 ranges rather than individual addresses.

Configure internal IPv6 subnets with BYOIP

Some deployments need IPv6 addresses that remain internal to GCP without internet announcement, useful for private interconnect or internal services.

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 mode INTERNAL_IPV6_SUBNETWORK_CREATION restricts addresses to internal use. The parent PublicAdvertisedPrefix must have ipv6AccessType set to INTERNAL. These addresses won’t be announced to the internet but can be used within GCP’s private network.

Beyond these examples

These snippets focus on specific prefix delegation features: IPv4 and IPv6 prefix delegation, hierarchical prefix structures, and mode-based allocation. They’re intentionally minimal rather than complete BYOIP implementations.

The examples require pre-existing infrastructure such as PublicAdvertisedPrefix resources with completed BYOIP onboarding and DNS verification. They focus on prefix configuration rather than the full BYOIP setup process.

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

  • Live migration configuration (isLiveMigration)
  • Enhanced IPv4 allocation features
  • Prefix lifecycle management and updates
  • Integration with VPC subnets or forwarding rules

These omissions are intentional: the goal is to illustrate how each delegation mode 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 & Setup
What's the difference between the different modes?

There are four modes for IPv6 Public Delegated Prefixes:

  • DELEGATION allows further sub-delegation to child prefixes
  • EXTERNAL_IPV6_FORWARDING_RULE_CREATION enables creation of forwarding rules
  • EXTERNAL_IPV6_SUBNETWORK_CREATION enables external subnet creation
  • INTERNAL_IPV6_SUBNETWORK_CREATION enables internal subnet creation
How do I create a hierarchical prefix structure?
Create a PublicAdvertisedPrefix first, then a root PublicDelegatedPrefix with mode set to DELEGATION, then create sub-prefixes with other modes, linking each child to its parent using parentPrefix.
What's the difference between using this with IPv4 vs IPv6?
IPv4 prefixes don’t support the mode property and allocatablePrefixLength always defaults to 32. IPv6 prefixes support multiple modes and configurable prefix lengths for sub-delegation.
Resource Constraints
What properties can't I change after creation?
Most properties are immutable: ipCidrRange, name, parentPrefix, region, mode, allocatablePrefixLength, description, project, and isLiveMigration. Changing any of these requires recreating the resource.
What are the naming requirements for a public delegated prefix?
Names must be 1-63 characters long and comply with RFC1035: start with a lowercase letter, contain only lowercase letters, digits, or dashes, and cannot end with a dash (regex: a-z?).
When can I use allocatablePrefixLength?
allocatablePrefixLength can only be set for IPv6 prefixes that are NOT in DELEGATION mode. It cannot be set for IPv4 prefixes, where it always defaults to 32.
IP Address Management
What format should I use for ipCidrRange?
Use standard CIDR notation (e.g., 127.127.0.0/24 for IPv4 or 2001:db8::/48 for IPv6). The range must be a subset of your parent prefix’s range.
What's the relationship between parentPrefix and ipCidrRange?
parentPrefix must reference either a PublicAdvertisedPrefix or another PublicDelegatedPrefix, and your ipCidrRange must be a subnet within the parent’s IP range.
Import & Migration
How do I import an existing public delegated prefix?
Use one of these formats: projects/{{project}}/regions/{{region}}/publicDelegatedPrefixes/{{name}}, {{project}}/{{region}}/{{name}}, {{region}}/{{name}}, or just {{name}}.

Using a different cloud?

Explore networking guides for other cloud providers: