Create and Configure Google Cloud SQL Database Instances

The gcp:sql/databaseInstance:DatabaseInstance resource, part of the Pulumi GCP provider, defines a Cloud SQL database instance: its engine version, machine tier, and network configuration. This guide focuses on three capabilities: database engine and tier selection, network access control (public, private, PSC), and performance features (caching, connection pooling).

Cloud SQL instances run in Google’s infrastructure but may reference your VPC networks, Service Networking connections, or Compute Engine instances for network configuration. The examples are intentionally small. Combine them with your own networking, backup policies, and user management.

Create a basic PostgreSQL instance

Most deployments start with a minimal configuration that specifies the database engine, region, 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 database engine and version. The settings block contains the tier (machine type) and other configuration. Without additional settings, the instance uses default network configuration with a public IP address.

Restrict network access with authorized networks

Production databases often limit connections to specific IP addresses, such as 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 lists IP addresses or ranges that can connect. Each entry has a name for identification and a value containing the IP address or CIDR range. This example dynamically builds the list from Compute Engine instance IPs.

Deploy with private IP and VPC peering

Applications running in VPCs often connect over private networks to avoid exposing database traffic to the internet.

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 (
	"fmt"

	"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 your VPC, and enablePrivatePathForGoogleCloudServices allows Google services to reach the instance. The dependsOn ensures VPC peering completes before instance creation; Cloud SQL doesn’t automatically wait for the servicenetworking.Connection.

Enable data caching for ENTERPRISE_PLUS edition

High-performance workloads can benefit from data caching, which reduces query latency by keeping 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 features like data caching. The dataCacheConfig block enables caching by setting dataCacheEnabled to true. This requires a performance-optimized tier (db-perf-optimized-N-*).

Configure Private Service Connect for consumer projects

Organizations with multiple projects can use Private Service Connect to allow specific consumer projects to access database instances without VPC peering.

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 Private Service Connect. The allowedConsumerProjects array lists project names that can create endpoints to this instance. Setting ipv4Enabled to false ensures connections use PSC only. REGIONAL availability type is required for PSC, which also requires backupConfiguration with binary logging enabled.

Beyond these examples

These snippets focus on specific instance-level features: database engine and tier selection, network access control (public IPs, private IPs, PSC), and performance features (data caching, connection pooling). They’re intentionally minimal rather than full database deployments.

The examples may reference pre-existing infrastructure such as VPC networks and subnets for private IP instances, Compute Engine instances for authorized network examples, and Service Networking connections for VPC peering. 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 point-in-time recovery
  • High availability and failover (availabilityType)
  • Database flags and maintenance windows
  • Encryption keys (encryptionKeyName)
  • Read replicas and replication configuration
  • User management and password policies

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 Google Cloud SQL Database Instances

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Security & User Management
Why was the default root user deleted from my instance?
Second-generation instances include a default ‘root’@’%’ user with no password, which the provider automatically deletes on creation for security. Use gcp.sql.User to create a custom user with a restricted host and strong password.
How do I delete my Cloud SQL instance?
Set deletionProtection to false and run pulumi update to write this to state before destroying. Note that this only protects within Pulumi; for full protection across all surfaces (API, gcloud, Console), use settings.deletionProtectionEnabled.
What's required to set up CMEK disk encryption?
Configure encryptionKeyName with the full path to your KMS key (must be in same region as instance). This requires manual setup: create a special service account, grant it Cloud KMS CryptoKey Encrypter/Decrypter role on your key. Note that encryptionKeyName is immutable.
Replication & Disaster Recovery
What happens during a switchover, and how do I avoid data loss?
Switchover swaps primary and replica roles. To avoid data loss, follow the exact steps for both instances and verify pulumi preview shows “0 to add, 0 to destroy” with no “must be replaced” messages. Only the two instances involved should have planned changes.
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.
Can I remove the replica_names field if I have no replicas?
No, don’t delete the replicaNames field entirely. Instead, set replicaNames = [] to indicate the instance has no replicas.
Networking & Connectivity
Why am I getting errors with private IP instances?
gcp.sql.DatabaseInstance doesn’t automatically interpolate values from gcp.servicenetworking.Connection. You must explicitly add a dependsOn reference to the connection resource.
How do I enable Private Service Connect (PSC) for my instance?
Configure settings.ipConfiguration.pscConfigs with pscEnabled = true and allowedConsumerProjects. Set ipv4Enabled = false, enable backups with binaryLogEnabled = true, and set availabilityType = "REGIONAL".
Instance Lifecycle & Configuration
Can I reuse an instance name after deletion?
No, instance names cannot be reused for up to one week after deletion. Consider letting the provider randomly generate names, or plan your naming carefully.
What happens when I update maintenanceVersion?
Updating maintenanceVersion causes an instance restart. You can only upgrade to versions listed in availableMaintenanceVersions; setting an older version than the current one is ignored. This property cannot be set during creation.
Should I use root_password or root_password_wo?
Only one can be set. Use rootPasswordWo if you need a write-only field that won’t be read from the API. To update rootPasswordWo, increment rootPasswordWoVersion to trigger the change.
Advanced Features
How do I enable data caching for better performance?
Use an ENTERPRISE_PLUS edition instance by setting settings.edition = "ENTERPRISE_PLUS" and settings.tier = "db-perf-optimized-N-2". Then configure settings.dataCacheConfig.dataCacheEnabled = true.
How do I enable managed connection pooling?
Set settings.connectionPoolConfigs.connectionPoolingEnabled = true and configure flags like max_client_connections. This requires ENTERPRISE_PLUS edition and a performance-optimized tier.
Can I restore from a backup using Pulumi?
While possible via restoreBackupContext, restoring from backup is an imperative action and not recommended via Pulumi. Adding or modifying this block triggers the restore action after resource creation/update.

Using a different cloud?

Explore database guides for other cloud providers: