Create and Configure Cloud SQL Instances

The gcp:sql/databaseInstance:DatabaseInstance resource, part of the Pulumi GCP provider, provisions a Cloud SQL database instance: its engine version, machine tier, and network configuration. This guide focuses on three capabilities: instance creation with version and tier selection, network access control, and performance features.

Cloud SQL instances run in a GCP project and region, and may reference VPC networks, service networking connections, or consumer projects. The examples are intentionally small. Combine them with your own backup policies, high availability settings, and database users.

Create a basic PostgreSQL instance with tier selection

Most deployments start by specifying the database engine, version, and machine tier.

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

const main = new gcp.sql.DatabaseInstance("main", {
    name: "main-instance",
    databaseVersion: "POSTGRES_15",
    region: "us-central1",
    settings: {
        tier: "db-f1-micro",
    },
});
import pulumi
import pulumi_gcp as gcp

main = gcp.sql.DatabaseInstance("main",
    name="main-instance",
    database_version="POSTGRES_15",
    region="us-central1",
    settings={
        "tier": "db-f1-micro",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabaseInstance(ctx, "main", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("main-instance"),
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			Region:          pulumi.String("us-central1"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier: pulumi.String("db-f1-micro"),
			},
		})
		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 main = new Gcp.Sql.DatabaseInstance("main", new()
    {
        Name = "main-instance",
        DatabaseVersion = "POSTGRES_15",
        Region = "us-central1",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
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 main = new DatabaseInstance("main", DatabaseInstanceArgs.builder()
            .name("main-instance")
            .databaseVersion("POSTGRES_15")
            .region("us-central1")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-f1-micro")
                .build())
            .build());

    }
}
resources:
  main:
    type: gcp:sql:DatabaseInstance
    properties:
      name: main-instance
      databaseVersion: POSTGRES_15
      region: us-central1
      settings:
        tier: db-f1-micro

The databaseVersion property selects the engine and version (PostgreSQL 15 here). The region determines where the instance runs. Inside settings, the tier property controls CPU and memory allocation. This minimal configuration uses default networking (public IP) and no backups.

Restrict network access with authorized IP ranges

Production databases accept connections only from specific application servers or on-premises networks.

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

const apps: gcp.compute.Instance[] = [];
for (const range = {value: 0}; range.value < 8; range.value++) {
    apps.push(new gcp.compute.Instance(`apps-${range.value}`, {
        networkInterfaces: [{
            accessConfigs: [{}],
            network: "default",
        }],
        name: `apps-${range.value + 1}`,
        machineType: "f1-micro",
        bootDisk: {
            initializeParams: {
                image: "ubuntu-os-cloud/ubuntu-1804-lts",
            },
        },
    }));
}
const dbNameSuffix = new random.index.Id("db_name_suffix", {byteLength: 4});
const onprem = [
    "192.168.1.2",
    "192.168.2.3",
];
const postgres = new gcp.sql.DatabaseInstance("postgres", {
    name: `postgres-instance-${dbNameSuffix.hex}`,
    databaseVersion: "POSTGRES_15",
    settings: {
        tier: "db-f1-micro",
        ipConfiguration: {
            authorizedNetworks: Object.entries(apps).map(([k, v]) => ({key: k, value: v})).apply(entries => entries.map(entry => ({
                name: entry.value.name,
                value: entry.value.networkInterface[0].accessConfig[0].natIp,
            }))),
            authorizedNetworks: onprem.map((v, k) => ({key: k, value: v})).map(entry2 => ({
                name: `onprem-${entry2.key}`,
                value: entry2.value,
            })),
        },
    },
});
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Random = Pulumi.Random;

return await Deployment.RunAsync(() => 
{
    var apps = new List<Gcp.Compute.Instance>();
    for (var rangeIndex = 0; rangeIndex < 8; rangeIndex++)
    {
        var range = new { Value = rangeIndex };
        apps.Add(new Gcp.Compute.Instance($"apps-{range.Value}", new()
        {
            NetworkInterfaces = new[]
            {
                new Gcp.Compute.Inputs.InstanceNetworkInterfaceArgs
                {
                    AccessConfigs = new[]
                    {
                        null,
                    },
                    Network = "default",
                },
            },
            Name = $"apps-{range.Value + 1}",
            MachineType = "f1-micro",
            BootDisk = new Gcp.Compute.Inputs.InstanceBootDiskArgs
            {
                InitializeParams = new Gcp.Compute.Inputs.InstanceBootDiskInitializeParamsArgs
                {
                    Image = "ubuntu-os-cloud/ubuntu-1804-lts",
                },
            },
        }));
    }
    var dbNameSuffix = new Random.Index.Id("db_name_suffix", new()
    {
        ByteLength = 4,
    });

    var onprem = new[]
    {
        "192.168.1.2",
        "192.168.2.3",
    };

    var postgres = new Gcp.Sql.DatabaseInstance("postgres", new()
    {
        Name = $"postgres-instance-{dbNameSuffix.Hex}",
        DatabaseVersion = "POSTGRES_15",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
            IpConfiguration = new Gcp.Sql.Inputs.DatabaseInstanceSettingsIpConfigurationArgs
            {
                AuthorizedNetworks = .Apply(entries => entries.Select(entry => 
                {
                    return 
                    {
                        { "name", entry.Value.Name },
                        { "value", entry.Value.NetworkInterface[0].AccessConfig[0].NatIp },
                    };
                }).ToList()),
                AuthorizedNetworks = onprem.Select((v, k) => new { Key = k, Value = v }).Select(entry2 => 
                {
                    return new Gcp.Sql.Inputs.DatabaseInstanceSettingsIpConfigurationAuthorizedNetworkArgs
                    {
                        Name = $"onprem-{entry2.Key}",
                        Value = entry2.Value,
                    };
                }).ToList(),
            },
        },
    });

});

The ipConfiguration block controls network access. The authorizedNetworks array whitelists specific IP addresses by name and CIDR range. Each entry grants access to one source. Without this configuration, the instance would be inaccessible from the public internet (unless using private IP).

Deploy with private IP and VPC peering

Applications in VPCs connect to databases over private IP addresses to avoid public internet exposure.

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

const privateNetwork = new gcp.compute.Network("private_network", {name: "private-network"});
const privateIpAddress = new gcp.compute.GlobalAddress("private_ip_address", {
    name: "private-ip-address",
    purpose: "VPC_PEERING",
    addressType: "INTERNAL",
    prefixLength: 16,
    network: privateNetwork.id,
});
const privateVpcConnection = new gcp.servicenetworking.Connection("private_vpc_connection", {
    network: privateNetwork.id,
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [privateIpAddress.name],
});
const dbNameSuffix = new random.index.Id("db_name_suffix", {byteLength: 4});
const instance = new gcp.sql.DatabaseInstance("instance", {
    name: `private-instance-${dbNameSuffix.hex}`,
    region: "us-central1",
    databaseVersion: "MYSQL_5_7",
    settings: {
        tier: "db-f1-micro",
        ipConfiguration: {
            ipv4Enabled: false,
            privateNetwork: privateNetwork.selfLink,
            enablePrivatePathForGoogleCloudServices: true,
        },
    },
}, {
    dependsOn: [privateVpcConnection],
});
import pulumi
import pulumi_gcp as gcp
import pulumi_random as random

private_network = gcp.compute.Network("private_network", name="private-network")
private_ip_address = gcp.compute.GlobalAddress("private_ip_address",
    name="private-ip-address",
    purpose="VPC_PEERING",
    address_type="INTERNAL",
    prefix_length=16,
    network=private_network.id)
private_vpc_connection = gcp.servicenetworking.Connection("private_vpc_connection",
    network=private_network.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[private_ip_address.name])
db_name_suffix = random.index.Id("db_name_suffix", byte_length=4)
instance = gcp.sql.DatabaseInstance("instance",
    name=f"private-instance-{db_name_suffix['hex']}",
    region="us-central1",
    database_version="MYSQL_5_7",
    settings={
        "tier": "db-f1-micro",
        "ip_configuration": {
            "ipv4_enabled": False,
            "private_network": private_network.self_link,
            "enable_private_path_for_google_cloud_services": True,
        },
    },
    opts = pulumi.ResourceOptions(depends_on=[private_vpc_connection]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		privateNetwork, err := compute.NewNetwork(ctx, "private_network", &compute.NetworkArgs{
			Name: pulumi.String("private-network"),
		})
		if err != nil {
			return err
		}
		privateIpAddress, err := compute.NewGlobalAddress(ctx, "private_ip_address", &compute.GlobalAddressArgs{
			Name:         pulumi.String("private-ip-address"),
			Purpose:      pulumi.String("VPC_PEERING"),
			AddressType:  pulumi.String("INTERNAL"),
			PrefixLength: pulumi.Int(16),
			Network:      privateNetwork.ID(),
		})
		if err != nil {
			return err
		}
		privateVpcConnection, err := servicenetworking.NewConnection(ctx, "private_vpc_connection", &servicenetworking.ConnectionArgs{
			Network: privateNetwork.ID(),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				privateIpAddress.Name,
			},
		})
		if err != nil {
			return err
		}
		dbNameSuffix, err := random.NewId(ctx, "db_name_suffix", &random.IdArgs{
			ByteLength: 4,
		})
		if err != nil {
			return err
		}
		_, err = sql.NewDatabaseInstance(ctx, "instance", &sql.DatabaseInstanceArgs{
			Name:            pulumi.Sprintf("private-instance-%v", dbNameSuffix.Hex),
			Region:          pulumi.String("us-central1"),
			DatabaseVersion: pulumi.String("MYSQL_5_7"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier: pulumi.String("db-f1-micro"),
				IpConfiguration: &sql.DatabaseInstanceSettingsIpConfigurationArgs{
					Ipv4Enabled:                             pulumi.Bool(false),
					PrivateNetwork:                          privateNetwork.SelfLink,
					EnablePrivatePathForGoogleCloudServices: pulumi.Bool(true),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			privateVpcConnection,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Random = Pulumi.Random;

return await Deployment.RunAsync(() => 
{
    var privateNetwork = new Gcp.Compute.Network("private_network", new()
    {
        Name = "private-network",
    });

    var privateIpAddress = new Gcp.Compute.GlobalAddress("private_ip_address", new()
    {
        Name = "private-ip-address",
        Purpose = "VPC_PEERING",
        AddressType = "INTERNAL",
        PrefixLength = 16,
        Network = privateNetwork.Id,
    });

    var privateVpcConnection = new Gcp.ServiceNetworking.Connection("private_vpc_connection", new()
    {
        Network = privateNetwork.Id,
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            privateIpAddress.Name,
        },
    });

    var dbNameSuffix = new Random.Index.Id("db_name_suffix", new()
    {
        ByteLength = 4,
    });

    var instance = new Gcp.Sql.DatabaseInstance("instance", new()
    {
        Name = $"private-instance-{dbNameSuffix.Hex}",
        Region = "us-central1",
        DatabaseVersion = "MYSQL_5_7",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
            IpConfiguration = new Gcp.Sql.Inputs.DatabaseInstanceSettingsIpConfigurationArgs
            {
                Ipv4Enabled = false,
                PrivateNetwork = privateNetwork.SelfLink,
                EnablePrivatePathForGoogleCloudServices = true,
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            privateVpcConnection,
        },
    });

});
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 com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.random.Id;
import com.pulumi.random.IdArgs;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsIpConfigurationArgs;
import com.pulumi.resources.CustomResourceOptions;
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 privateNetwork = new Network("privateNetwork", NetworkArgs.builder()
            .name("private-network")
            .build());

        var privateIpAddress = new GlobalAddress("privateIpAddress", GlobalAddressArgs.builder()
            .name("private-ip-address")
            .purpose("VPC_PEERING")
            .addressType("INTERNAL")
            .prefixLength(16)
            .network(privateNetwork.id())
            .build());

        var privateVpcConnection = new Connection("privateVpcConnection", ConnectionArgs.builder()
            .network(privateNetwork.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(privateIpAddress.name())
            .build());

        var dbNameSuffix = new Id("dbNameSuffix", IdArgs.builder()
            .byteLength(4)
            .build());

        var instance = new DatabaseInstance("instance", DatabaseInstanceArgs.builder()
            .name(String.format("private-instance-%s", dbNameSuffix.hex()))
            .region("us-central1")
            .databaseVersion("MYSQL_5_7")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-f1-micro")
                .ipConfiguration(DatabaseInstanceSettingsIpConfigurationArgs.builder()
                    .ipv4Enabled(false)
                    .privateNetwork(privateNetwork.selfLink())
                    .enablePrivatePathForGoogleCloudServices(true)
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(privateVpcConnection)
                .build());

    }
}
resources:
  privateNetwork:
    type: gcp:compute:Network
    name: private_network
    properties:
      name: private-network
  privateIpAddress:
    type: gcp:compute:GlobalAddress
    name: private_ip_address
    properties:
      name: private-ip-address
      purpose: VPC_PEERING
      addressType: INTERNAL
      prefixLength: 16
      network: ${privateNetwork.id}
  privateVpcConnection:
    type: gcp:servicenetworking:Connection
    name: private_vpc_connection
    properties:
      network: ${privateNetwork.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${privateIpAddress.name}
  dbNameSuffix:
    type: random:Id
    name: db_name_suffix
    properties:
      byteLength: 4
  instance:
    type: gcp:sql:DatabaseInstance
    properties:
      name: private-instance-${dbNameSuffix.hex}
      region: us-central1
      databaseVersion: MYSQL_5_7
      settings:
        tier: db-f1-micro
        ipConfiguration:
          ipv4Enabled: false
          privateNetwork: ${privateNetwork.selfLink}
          enablePrivatePathForGoogleCloudServices: true
    options:
      dependsOn:
        - ${privateVpcConnection}

Setting ipv4Enabled to false disables the public IP. The privateNetwork property references a VPC network. Before creating the instance, you must establish VPC peering through servicenetworking.Connection. The dependsOn ensures peering completes first; without it, instance creation fails.

Enable data caching for ENTERPRISE_PLUS edition

High-performance workloads benefit from data caching, which keeps frequently accessed data in memory.

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

const main = new gcp.sql.DatabaseInstance("main", {
    name: "enterprise-plus-main-instance",
    databaseVersion: "MYSQL_8_0_31",
    settings: {
        tier: "db-perf-optimized-N-2",
        edition: "ENTERPRISE_PLUS",
        dataCacheConfig: {
            dataCacheEnabled: true,
        },
    },
});
import pulumi
import pulumi_gcp as gcp

main = gcp.sql.DatabaseInstance("main",
    name="enterprise-plus-main-instance",
    database_version="MYSQL_8_0_31",
    settings={
        "tier": "db-perf-optimized-N-2",
        "edition": "ENTERPRISE_PLUS",
        "data_cache_config": {
            "data_cache_enabled": True,
        },
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabaseInstance(ctx, "main", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("enterprise-plus-main-instance"),
			DatabaseVersion: pulumi.String("MYSQL_8_0_31"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier:    pulumi.String("db-perf-optimized-N-2"),
				Edition: pulumi.String("ENTERPRISE_PLUS"),
				DataCacheConfig: &sql.DatabaseInstanceSettingsDataCacheConfigArgs{
					DataCacheEnabled: pulumi.Bool(true),
				},
			},
		})
		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 main = new Gcp.Sql.DatabaseInstance("main", new()
    {
        Name = "enterprise-plus-main-instance",
        DatabaseVersion = "MYSQL_8_0_31",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-perf-optimized-N-2",
            Edition = "ENTERPRISE_PLUS",
            DataCacheConfig = new Gcp.Sql.Inputs.DatabaseInstanceSettingsDataCacheConfigArgs
            {
                DataCacheEnabled = true,
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsDataCacheConfigArgs;
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 main = new DatabaseInstance("main", DatabaseInstanceArgs.builder()
            .name("enterprise-plus-main-instance")
            .databaseVersion("MYSQL_8_0_31")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-perf-optimized-N-2")
                .edition("ENTERPRISE_PLUS")
                .dataCacheConfig(DatabaseInstanceSettingsDataCacheConfigArgs.builder()
                    .dataCacheEnabled(true)
                    .build())
                .build())
            .build());

    }
}
resources:
  main:
    type: gcp:sql:DatabaseInstance
    properties:
      name: enterprise-plus-main-instance
      databaseVersion: MYSQL_8_0_31
      settings:
        tier: db-perf-optimized-N-2
        edition: ENTERPRISE_PLUS
        dataCacheConfig:
          dataCacheEnabled: true

The edition property selects ENTERPRISE_PLUS, which unlocks advanced features. Inside dataCacheConfig, setting dataCacheEnabled to true activates in-memory caching. This reduces query latency for read-heavy workloads. The tier must support the edition (db-perf-optimized tiers work here).

Configure Private Service Connect for consumer access

Private Service Connect allows consumer projects to connect without VPC peering, simplifying multi-tenant architectures.

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

const main = new gcp.sql.DatabaseInstance("main", {
    name: "psc-enabled-main-instance",
    databaseVersion: "MYSQL_8_0",
    settings: {
        tier: "db-f1-micro",
        ipConfiguration: {
            pscConfigs: [{
                pscEnabled: true,
                allowedConsumerProjects: ["allowed-consumer-project-name"],
            }],
            ipv4Enabled: false,
        },
        backupConfiguration: {
            enabled: true,
            binaryLogEnabled: true,
        },
        availabilityType: "REGIONAL",
    },
});
import pulumi
import pulumi_gcp as gcp

main = gcp.sql.DatabaseInstance("main",
    name="psc-enabled-main-instance",
    database_version="MYSQL_8_0",
    settings={
        "tier": "db-f1-micro",
        "ip_configuration": {
            "psc_configs": [{
                "psc_enabled": True,
                "allowed_consumer_projects": ["allowed-consumer-project-name"],
            }],
            "ipv4_enabled": False,
        },
        "backup_configuration": {
            "enabled": True,
            "binary_log_enabled": True,
        },
        "availability_type": "REGIONAL",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabaseInstance(ctx, "main", &sql.DatabaseInstanceArgs{
			Name:            pulumi.String("psc-enabled-main-instance"),
			DatabaseVersion: pulumi.String("MYSQL_8_0"),
			Settings: &sql.DatabaseInstanceSettingsArgs{
				Tier: pulumi.String("db-f1-micro"),
				IpConfiguration: &sql.DatabaseInstanceSettingsIpConfigurationArgs{
					PscConfigs: sql.DatabaseInstanceSettingsIpConfigurationPscConfigArray{
						&sql.DatabaseInstanceSettingsIpConfigurationPscConfigArgs{
							PscEnabled: pulumi.Bool(true),
							AllowedConsumerProjects: pulumi.StringArray{
								pulumi.String("allowed-consumer-project-name"),
							},
						},
					},
					Ipv4Enabled: pulumi.Bool(false),
				},
				BackupConfiguration: &sql.DatabaseInstanceSettingsBackupConfigurationArgs{
					Enabled:          pulumi.Bool(true),
					BinaryLogEnabled: pulumi.Bool(true),
				},
				AvailabilityType: pulumi.String("REGIONAL"),
			},
		})
		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 main = new Gcp.Sql.DatabaseInstance("main", new()
    {
        Name = "psc-enabled-main-instance",
        DatabaseVersion = "MYSQL_8_0",
        Settings = new Gcp.Sql.Inputs.DatabaseInstanceSettingsArgs
        {
            Tier = "db-f1-micro",
            IpConfiguration = new Gcp.Sql.Inputs.DatabaseInstanceSettingsIpConfigurationArgs
            {
                PscConfigs = new[]
                {
                    new Gcp.Sql.Inputs.DatabaseInstanceSettingsIpConfigurationPscConfigArgs
                    {
                        PscEnabled = true,
                        AllowedConsumerProjects = new[]
                        {
                            "allowed-consumer-project-name",
                        },
                    },
                },
                Ipv4Enabled = false,
            },
            BackupConfiguration = new Gcp.Sql.Inputs.DatabaseInstanceSettingsBackupConfigurationArgs
            {
                Enabled = true,
                BinaryLogEnabled = true,
            },
            AvailabilityType = "REGIONAL",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.sql.DatabaseInstance;
import com.pulumi.gcp.sql.DatabaseInstanceArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsIpConfigurationArgs;
import com.pulumi.gcp.sql.inputs.DatabaseInstanceSettingsBackupConfigurationArgs;
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 main = new DatabaseInstance("main", DatabaseInstanceArgs.builder()
            .name("psc-enabled-main-instance")
            .databaseVersion("MYSQL_8_0")
            .settings(DatabaseInstanceSettingsArgs.builder()
                .tier("db-f1-micro")
                .ipConfiguration(DatabaseInstanceSettingsIpConfigurationArgs.builder()
                    .pscConfigs(DatabaseInstanceSettingsIpConfigurationPscConfigArgs.builder()
                        .pscEnabled(true)
                        .allowedConsumerProjects("allowed-consumer-project-name")
                        .build())
                    .ipv4Enabled(false)
                    .build())
                .backupConfiguration(DatabaseInstanceSettingsBackupConfigurationArgs.builder()
                    .enabled(true)
                    .binaryLogEnabled(true)
                    .build())
                .availabilityType("REGIONAL")
                .build())
            .build());

    }
}
resources:
  main:
    type: gcp:sql:DatabaseInstance
    properties:
      name: psc-enabled-main-instance
      databaseVersion: MYSQL_8_0
      settings:
        tier: db-f1-micro
        ipConfiguration:
          pscConfigs:
            - pscEnabled: true
              allowedConsumerProjects:
                - allowed-consumer-project-name
          ipv4Enabled: false
        backupConfiguration:
          enabled: true
          binaryLogEnabled: true
        availabilityType: REGIONAL

The pscConfigs block enables PSC by setting pscEnabled to true. The allowedConsumerProjects array lists which projects can create PSC endpoints to this instance. Setting ipv4Enabled to false ensures all access goes through PSC. The availabilityType of REGIONAL provides high availability across zones.

Beyond these examples

These snippets focus on specific instance-level features: basic instance creation and tier selection, network access control, and performance features like data caching and connection pooling. They’re intentionally minimal rather than full database deployments.

The examples may reference pre-existing infrastructure such as VPC networks and service networking connections, Compute Engine instances for IP whitelisting, and consumer projects for PSC configurations. They focus on configuring the instance rather than provisioning everything around it.

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

  • Backup configuration and retention policies
  • High availability and failover (availabilityType)
  • Maintenance windows and update timing
  • Encryption keys (encryptionKeyName)
  • Read replicas and replication setup
  • Database flags and custom settings

These omissions are intentional: the goal is to illustrate how each instance feature is wired, not provide drop-in database modules. See the Cloud SQL DatabaseInstance resource reference for all available configuration options.

Let's create and Configure Cloud SQL Instances

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Deletion & Protection
Why can't I destroy my Cloud SQL instance?
Instances have deletionProtection set to true by default. You must explicitly set deletionProtection=false and run pulumi update before destroying the instance. Note that this only protects within Pulumi; for protection across all surfaces (API, gcloud, Console), use settings.deletionProtectionEnabled.
Can I reuse an instance name immediately after deletion?
No, instance names cannot be reused for up to one week after deletion. Consider using unique name generation with random suffixes (as shown in examples) to avoid conflicts.
Security & Access
What's the default root user and why should I change it?
Second-generation instances include a default 'root'@'%' user with no password. The provider automatically deletes this user on instance creation. You should use gcp.sql.User to define a custom user with a restricted host and strong password.
How do I restrict network access to specific IP addresses?
Configure settings.ipConfiguration.authorizedNetworks with a list of objects containing name and value (IP address) for each allowed network.
What's the difference between rootPassword and rootPasswordWo?
Only one can be set. rootPasswordWo is write-only and its value won’t be read from the API or updated in state. Use rootPasswordWoVersion to trigger updates to rootPasswordWo.
Private Networking & Connectivity
Why am I getting errors when creating a private IP instance?
The instance doesn’t automatically interpolate values from gcp.servicenetworking.Connection. You must explicitly add a dependsOn reference to the connection resource, as shown in the Private IP Instance example.
How do I enable PSC (Private Service Connect) connectivity?
Configure settings.ipConfiguration.pscConfigs with pscEnabled=true, allowedConsumerProjects, and set ipv4Enabled=false. You must also enable backupConfiguration.enabled=true and set availabilityType='REGIONAL'.
Replication & High Availability
What's required to create a read replica?
Set masterInstanceName to the primary instance name. The master must have binaryLogEnabled set and existing backups configured.
How do I safely perform a switchover between primary and replica?
Follow the switchover steps for your database type (MySQL/PostgreSQL or SQL Server). Change instanceType, update masterInstanceName, adjust replicaNames, and modify replication configuration. Critical: verify pulumi preview shows “0 to add, 0 to destroy” and no “must be replaced” messages.
What happens to replicaNames during switchover?
Don’t delete the replicaNames field even if no replicas remain. Set replicaNames = [] to indicate the instance has no replicas.
Backup & Recovery
Should I use restore operations in Pulumi configurations?
No, restore operations (backupdrBackup, pointInTimeRestoreContext, restoreBackupContext) are imperative actions and not recommended via Pulumi. Adding or modifying these fields triggers restore during resource creation/update. Perform restores manually when needed.
What's required to restore from a Backup and DR backup?
The backup must be in active state. List backups using gcp.backupdisasterrecovery.getBackup and use the full backup path in backupdrBackup.
Configuration & Maintenance
Will updating maintenanceVersion cause downtime?
Yes, updating maintenanceVersion causes an instance restart. Plan maintenance windows accordingly. Setting a version older than the current one is ignored.
Why aren't my imported fields showing diffs?
Some fields like replicaConfiguration won’t show a diff if they’re unset in your config but set on the server. After importing, verify your config has all expected fields set; no diff doesn’t guarantee your config can reproduce the resource.

Using a different cloud?

Explore database guides for other cloud providers: