Create and Configure GCP VPC Networks

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

VPC networks are the foundation for subnets, firewall rules, and Cloud Router configurations. The examples are intentionally small. Combine them with your own subnet, firewall, and routing resources.

Create a VPC network with default settings

Most deployments start with a named VPC network that relies on 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 the 10.128.0.0/9 range) with REGIONAL routing mode.

Configure MTU for jumbo frames or compatibility

Networks handling large data transfers or matching on-premises MTU settings can adjust packet size to optimize throughput.

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 Transmission Unit in bytes. Values above 1500 enable jumbo frames for higher throughput but may require compatible infrastructure. 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 or after classic VPC firewall rules. Setting it to BEFORE_CLASSIC_FIREWALL gives organization-level policies precedence.

Enable global routing for multi-region connectivity

Applications spanning multiple regions need Cloud Routers to advertise routes globally rather than limiting advertisements to the router’s region.

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. GLOBAL mode allows Cloud Routers to advertise all network subnets across regions, enabling cross-region connectivity without additional configuration.

Tune BGP path selection with MED comparison

Networks with multiple BGP peers can influence path selection by comparing Multi-Exit Discriminator values across different Autonomous Systems.

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. When set to STANDARD, bgpAlwaysCompareMed enables MED comparison across different neighbor ASNs, and bgpInterRegionCost controls how inter-region costs affect path selection. These settings require GLOBAL routing mode.

Beyond these examples

These snippets focus on specific network-level features: subnet creation modes, MTU tuning and firewall policy ordering, and BGP routing configuration and 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, and firewall policies for enforcement order examples. They focus on configuring the network rather than provisioning everything around it.

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

  • Subnet creation (handled by companion Subnetwork resources)
  • IPv6 configuration (enableUlaInternalIpv6, internalIpv6Range)
  • Network profiles for specialized topologies
  • Default route deletion (deleteDefaultRoutesOnCreate)

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?
Auto mode (autoCreateSubnetworks: true) automatically creates a subnet in each region across the 10.128.0.0/9 address range. Custom mode (autoCreateSubnetworks: false) requires you to explicitly create subnet resources.
What properties can't be changed after creating a network?
The following properties are immutable and require network recreation: name, project, autoCreateSubnetworks, description, internalIpv6Range, networkProfile, and params.
What are the naming requirements for a VPC network?
Network names must be 1-63 characters long and match the pattern [a-z]([-a-z0-9]*[a-z0-9])?. The first character must be a lowercase letter, and the last character cannot be a dash.
MTU & Packet Handling
What MTU should I use for my network?
The default MTU is 1460 bytes (range: 1300-8896). Use standard MTU (1460-1500) for Internet-facing traffic. Packets larger than 1500 bytes can be subject to TCP-MSS clamping or dropped with ICMP Fragmentation-Needed messages when routed to the Internet or VPCs with varying MTUs. Jumbo frames (up to 8896) are only suitable for internal VPC traffic with consistent MTU across all connected networks.
BGP & Routing
What's the difference between REGIONAL and GLOBAL routing modes?
REGIONAL mode means cloud routers only advertise routes for subnets in the same region. GLOBAL mode means cloud routers advertise routes for all subnets across all regions.
What are the BGP best path selection modes?
You can choose LEGACY or STANDARD mode via bgpBestPathSelectionMode. STANDARD mode enables additional BGP configuration options like bgpAlwaysCompareMed and bgpInterRegionCost.
Why can't I set bgpAlwaysCompareMed on my network?
The bgpAlwaysCompareMed property can only be set when bgpBestPathSelectionMode is STANDARD. Set the mode to STANDARD first, then configure MED comparison.
How do I clear the bgpAlwaysCompareMed setting?
Set deleteBgpAlwaysCompareMed: true to clear the bgpAlwaysCompareMed field. When false (default), the field retains the value specified in your configuration.
IPv6 & Advanced Features
How do I enable internal IPv6 on my network?
Set enableUlaInternalIpv6: true to assign a /48 range from the Google-defined ULA prefix fd20::/20. You can optionally specify a /48 range via internalIpv6Range, but the operation will fail if that range is already in use.
What happens if I enable deleteDefaultRoutesOnCreate?
When set to true, default routes (0.0.0.0/0) are deleted immediately after network creation. This defaults to false.
Firewall & Security
What's the default firewall policy enforcement order?
The default is AFTER_CLASSIC_FIREWALL, meaning network firewall policies are evaluated after classic firewall rules. You can set networkFirewallPolicyEnforcementOrder to BEFORE_CLASSIC_FIREWALL to reverse this order.
Deprecations & Migrations
Should I use numericId or networkId?
Use networkId. The numericId output property is deprecated and will be removed in a future major release.

Using a different cloud?

Explore networking guides for other cloud providers: