Create and Configure GCP VPC Networks

The gcp:compute/network:Network resource, part of the Pulumi GCP provider, provisions a VPC network that provides isolated networking for compute resources, defining subnet creation mode, routing behavior, and BGP configuration. This guide focuses on three capabilities: subnet creation modes, MTU and firewall policy ordering, and global routing with BGP path selection.

VPC networks are project-level resources that may reference Cloud Routers for BGP configuration or hierarchical firewall policies for enforcement order. The examples are intentionally small. Combine them with your own subnets, firewall rules, and routing configuration.

Create a VPC network with default settings

Most deployments start with a named VPC network that accepts GCP defaults for subnet creation and routing.

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

const vpcNetwork = new gcp.compute.Network("vpc_network", {name: "vpc-network"});
import pulumi
import pulumi_gcp as gcp

vpc_network = gcp.compute.Network("vpc_network", name="vpc-network")
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 {
		_, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
			Name: pulumi.String("vpc-network"),
		})
		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 vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
    {
        Name = "vpc-network",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
            .name("vpc-network")
            .build());

    }
}
resources:
  vpcNetwork:
    type: gcp:compute:Network
    name: vpc_network
    properties:
      name: vpc-network

The name property identifies the network. Without additional configuration, GCP creates the network in auto subnet mode (one subnet per region across 10.128.0.0/9) with REGIONAL routing mode. This provides immediate connectivity for compute resources without manual subnet provisioning.

Configure MTU for jumbo frames or compatibility

Networks handling large data transfers or matching on-premises MTU settings can adjust the Maximum Transmission Unit.

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

const vpcNetwork = new gcp.compute.Network("vpc_network", {
    project: "my-project-name",
    name: "vpc-network",
    autoCreateSubnetworks: true,
    mtu: 1460,
});
import pulumi
import pulumi_gcp as gcp

vpc_network = gcp.compute.Network("vpc_network",
    project="my-project-name",
    name="vpc-network",
    auto_create_subnetworks=True,
    mtu=1460)
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 {
		_, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
			Project:               pulumi.String("my-project-name"),
			Name:                  pulumi.String("vpc-network"),
			AutoCreateSubnetworks: pulumi.Bool(true),
			Mtu:                   pulumi.Int(1460),
		})
		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 vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
    {
        Project = "my-project-name",
        Name = "vpc-network",
        AutoCreateSubnetworks = true,
        Mtu = 1460,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
            .project("my-project-name")
            .name("vpc-network")
            .autoCreateSubnetworks(true)
            .mtu(1460)
            .build());

    }
}
resources:
  vpcNetwork:
    type: gcp:compute:Network
    name: vpc_network
    properties:
      project: my-project-name
      name: vpc-network
      autoCreateSubnetworks: true
      mtu: 1460

The mtu property sets the maximum packet size in bytes (1300-8896). The default is 1460 bytes; values above 1500 enable jumbo frames but may cause fragmentation when routing to the Internet or networks with standard MTU. The autoCreateSubnetworks property explicitly enables auto subnet mode.

Apply firewall policies before classic rules

Organizations using hierarchical firewall policies can control evaluation order relative to VPC-level firewall rules.

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

const vpcNetwork = new gcp.compute.Network("vpc_network", {
    project: "my-project-name",
    name: "vpc-network",
    autoCreateSubnetworks: true,
    networkFirewallPolicyEnforcementOrder: "BEFORE_CLASSIC_FIREWALL",
});
import pulumi
import pulumi_gcp as gcp

vpc_network = gcp.compute.Network("vpc_network",
    project="my-project-name",
    name="vpc-network",
    auto_create_subnetworks=True,
    network_firewall_policy_enforcement_order="BEFORE_CLASSIC_FIREWALL")
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 {
		_, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
			Project:                               pulumi.String("my-project-name"),
			Name:                                  pulumi.String("vpc-network"),
			AutoCreateSubnetworks:                 pulumi.Bool(true),
			NetworkFirewallPolicyEnforcementOrder: pulumi.String("BEFORE_CLASSIC_FIREWALL"),
		})
		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 vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
    {
        Project = "my-project-name",
        Name = "vpc-network",
        AutoCreateSubnetworks = true,
        NetworkFirewallPolicyEnforcementOrder = "BEFORE_CLASSIC_FIREWALL",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
            .project("my-project-name")
            .name("vpc-network")
            .autoCreateSubnetworks(true)
            .networkFirewallPolicyEnforcementOrder("BEFORE_CLASSIC_FIREWALL")
            .build());

    }
}
resources:
  vpcNetwork:
    type: gcp:compute:Network
    name: vpc_network
    properties:
      project: my-project-name
      name: vpc-network
      autoCreateSubnetworks: true
      networkFirewallPolicyEnforcementOrder: BEFORE_CLASSIC_FIREWALL

The networkFirewallPolicyEnforcementOrder property determines whether hierarchical policies evaluate BEFORE_CLASSIC_FIREWALL or AFTER_CLASSIC_FIREWALL (default). Setting it to BEFORE_CLASSIC_FIREWALL ensures organization-wide policies take precedence over network-specific rules.

Enable global routing for multi-region connectivity

Networks with Cloud Routers in multiple regions need global routing to advertise routes across regions.

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

const vpcNetwork = new gcp.compute.Network("vpc_network", {
    project: "my-project-name",
    name: "vpc-network",
    routingMode: "GLOBAL",
});
import pulumi
import pulumi_gcp as gcp

vpc_network = gcp.compute.Network("vpc_network",
    project="my-project-name",
    name="vpc-network",
    routing_mode="GLOBAL")
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 {
		_, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
			Project:     pulumi.String("my-project-name"),
			Name:        pulumi.String("vpc-network"),
			RoutingMode: 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 vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
    {
        Project = "my-project-name",
        Name = "vpc-network",
        RoutingMode = "GLOBAL",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
            .project("my-project-name")
            .name("vpc-network")
            .routingMode("GLOBAL")
            .build());

    }
}
resources:
  vpcNetwork:
    type: gcp:compute:Network
    name: vpc_network
    properties:
      project: my-project-name
      name: vpc-network
      routingMode: GLOBAL

The routingMode property controls route advertisement scope. REGIONAL mode (default) limits Cloud Routers to advertising routes within their region; GLOBAL mode allows routers to advertise all network routes across regions, enabling cross-region communication without additional configuration.

Tune BGP path selection with MED comparison

Networks with multiple BGP peers can use STANDARD mode for advanced path selection features.

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

const vpcNetwork = new gcp.compute.Network("vpc_network", {
    project: "my-project-name",
    name: "vpc-network",
    routingMode: "GLOBAL",
    bgpBestPathSelectionMode: "STANDARD",
    bgpAlwaysCompareMed: true,
    bgpInterRegionCost: "ADD_COST_TO_MED",
});
import pulumi
import pulumi_gcp as gcp

vpc_network = gcp.compute.Network("vpc_network",
    project="my-project-name",
    name="vpc-network",
    routing_mode="GLOBAL",
    bgp_best_path_selection_mode="STANDARD",
    bgp_always_compare_med=True,
    bgp_inter_region_cost="ADD_COST_TO_MED")
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 {
		_, err := compute.NewNetwork(ctx, "vpc_network", &compute.NetworkArgs{
			Project:                  pulumi.String("my-project-name"),
			Name:                     pulumi.String("vpc-network"),
			RoutingMode:              pulumi.String("GLOBAL"),
			BgpBestPathSelectionMode: pulumi.String("STANDARD"),
			BgpAlwaysCompareMed:      pulumi.Bool(true),
			BgpInterRegionCost:       pulumi.String("ADD_COST_TO_MED"),
		})
		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 vpcNetwork = new Gcp.Compute.Network("vpc_network", new()
    {
        Project = "my-project-name",
        Name = "vpc-network",
        RoutingMode = "GLOBAL",
        BgpBestPathSelectionMode = "STANDARD",
        BgpAlwaysCompareMed = true,
        BgpInterRegionCost = "ADD_COST_TO_MED",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
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 vpcNetwork = new Network("vpcNetwork", NetworkArgs.builder()
            .project("my-project-name")
            .name("vpc-network")
            .routingMode("GLOBAL")
            .bgpBestPathSelectionMode("STANDARD")
            .bgpAlwaysCompareMed(true)
            .bgpInterRegionCost("ADD_COST_TO_MED")
            .build());

    }
}
resources:
  vpcNetwork:
    type: gcp:compute:Network
    name: vpc_network
    properties:
      project: my-project-name
      name: vpc-network
      routingMode: GLOBAL
      bgpBestPathSelectionMode: STANDARD
      bgpAlwaysCompareMed: true
      bgpInterRegionCost: ADD_COST_TO_MED

The bgpBestPathSelectionMode property switches from LEGACY to STANDARD algorithm. In STANDARD mode, bgpAlwaysCompareMed enables MED comparison across different neighbor ASNs, and bgpInterRegionCost controls how inter-region costs affect MED values (ADD_COST_TO_MED adds regional cost to MED for path selection).

Beyond these examples

These snippets focus on specific network-level features: subnet creation modes, MTU and firewall policy ordering, and routing modes and BGP path selection. They’re intentionally minimal rather than full networking deployments.

The examples may reference pre-existing infrastructure such as GCP projects with Compute Engine API enabled, Cloud Routers and BGP sessions for routing examples, and hierarchical firewall policies for enforcement order configuration. They focus on configuring the network rather than provisioning everything around it.

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

  • Subnet resource creation (autoCreateSubnetworks handles this automatically or requires separate Subnetwork resources)
  • IPv6 configuration (enableUlaInternalIpv6, internalIpv6Range)
  • Network profiles and default route deletion
  • Description and params fields

These omissions are intentional: the goal is to illustrate how each network feature is wired, not provide drop-in networking modules. See the Compute Network resource reference for all available configuration options.

Let's create and Configure GCP VPC Networks

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Network Configuration & Subnets
What's the difference between auto and custom subnet mode?
When autoCreateSubnetworks is true, the network creates subnets automatically in each region using the 10.128.0.0/9 address range. When false, you must explicitly create and connect subnet resources. This property is immutable after network creation.
What happens if I configure jumbo frames with MTU above 1500?
Packets larger than 1500 bytes can be subject to TCP-MSS clamping or dropped with an ICMP Fragmentation-Needed message when routed to the Internet or other VPCs with varying MTUs. The MTU range is 1300-8896 bytes, with a default of 1460.
How do I prevent default routes from being created?
Set deleteDefaultRoutesOnCreate to true to delete default routes (0.0.0.0/0) immediately after network creation. This defaults to false.
Immutability & Lifecycle
What properties can't I change after network creation?
The following properties are immutable: name, project, autoCreateSubnetworks, description, internalIpv6Range, networkProfile, and params. Changing any of these requires recreating the network.
Why do I need to recreate my network to change the description?
The description field is immutable and can only be set at creation time. Modifying it requires recreating the entire network resource.
BGP & Routing
Should I use REGIONAL or GLOBAL routing mode?
Use REGIONAL if cloud routers should only advertise routes for subnetworks in the same region. Use GLOBAL to advertise routes for all subnetworks across all regions.
Why can't I set bgpAlwaysCompareMed?
The bgpAlwaysCompareMed property can only be set when bgpBestPathSelectionMode is STANDARD. Set the mode to STANDARD first, then configure MED comparison.
Firewall & Security
What does networkFirewallPolicyEnforcementOrder control?
This property sets the evaluation order of Firewall Rules and Firewall Policies. The default is AFTER_CLASSIC_FIREWALL. You can set it to BEFORE_CLASSIC_FIREWALL to evaluate policies before classic rules.
IPv6 Configuration
How do I enable IPv6 on my VPC network?
Set enableUlaInternalIpv6 to true to assign a /48 range from the Google-defined ULA prefix fd20::/20. You can optionally specify a custom /48 range using internalIpv6Range.
Naming & Identification
What are the naming requirements for a VPC network?
The name must be 1-63 characters long and match the regex [a-z][-a-z0-9]*[a-z0-9]. It must start with a lowercase letter, contain only lowercase letters, digits, or dashes, and cannot end with a dash.
Should I use numericId or networkId?
Use networkId. The numericId field is deprecated and will be removed in a future major release.

Using a different cloud?

Explore networking guides for other cloud providers: