Skip to main content
GCPDatabasesintermediate

Cloud SQL Guide

Manage MySQL and PostgreSQL on GCP: HA, replicas, maintenance, Auth Proxy, IAM auth, and performance tuning.

CloudToolStack Team24 min readPublished Mar 14, 2026

Prerequisites

  • Basic understanding of relational databases (MySQL or PostgreSQL)
  • GCP account with Cloud SQL Admin permissions

What Is Cloud SQL?

Cloud SQL is Google Cloud's fully managed relational database service supporting MySQL, PostgreSQL, and SQL Server. It handles the operational burden of database management including provisioning, patching, backups, replication, failover, and scaling. Cloud SQL instances run in Google's data centers with configurable machine types, storage, high availability, and read replicas.

Unlike AlloyDB (which is a PostgreSQL-compatible database with custom Google storage) or Cloud Spanner (which provides global strong consistency), Cloud SQL runs standard MySQL and PostgreSQL engines. This means you get full wire-protocol compatibility, can use your existing tools and ORMs, and can migrate from on-premises or other clouds with minimal application changes.

This guide covers instance creation and sizing, high availability configuration, read replicas, maintenance windows, Cloud SQL Auth Proxy, IAM authentication, connectivity patterns, and performance optimization.

Cloud SQL Editions

Cloud SQL offers two editions: Enterprise (standard managed database with SSD/HDD storage) and Enterprise Plus (advanced edition with data cache for low-latency reads, up to 128 vCPUs, and near-zero downtime maintenance). Choose Enterprise for most workloads; use Enterprise Plus for latency-sensitive, high-throughput applications.

Creating a Cloud SQL Instance

bash
# Create a PostgreSQL instance
gcloud sql instances create myapp-db \
  --database-version=POSTGRES_16 \
  --tier=db-custom-4-16384 \
  --region=us-central1 \
  --availability-type=REGIONAL \
  --storage-type=SSD \
  --storage-size=100GB \
  --storage-auto-increase \
  --backup-start-time=02:00 \
  --enable-bin-log \
  --maintenance-window-day=SUN \
  --maintenance-window-hour=4 \
  --maintenance-release-channel=production \
  --database-flags=max_connections=200,log_min_duration_statement=1000 \
  --root-password="YOUR_SECURE_PASSWORD" \
  --labels=env=production,team=backend

# Create a MySQL instance
gcloud sql instances create myapp-mysql \
  --database-version=MYSQL_8_0 \
  --tier=db-n1-standard-4 \
  --region=us-central1 \
  --availability-type=REGIONAL \
  --storage-type=SSD \
  --storage-size=100GB \
  --storage-auto-increase \
  --backup-start-time=02:00

# Create a database
gcloud sql databases create myapp \
  --instance=myapp-db

# Create a user
gcloud sql users create app_user \
  --instance=myapp-db \
  --password="USER_PASSWORD"

# List instances
gcloud sql instances list \
  --format='table(name, databaseVersion, settings.tier, region, state)'

High Availability Configuration

Cloud SQL high availability (HA) uses a regional configuration with a primary instance and a standby instance in a different zone within the same region. If the primary fails, Cloud SQL automatically fails over to the standby. Failover typically completes in 60-120 seconds.

ConfigurationAvailabilityFailover TimeCost
Zonal (single zone)99.95% SLAManual intervention1x base cost
Regional (HA)99.99% SLA60-120 seconds (auto)~2x base cost
bash
# Enable HA on an existing instance
gcloud sql instances patch myapp-db \
  --availability-type=REGIONAL

# Simulate failover (for testing)
gcloud sql instances failover myapp-db

# Check HA status
gcloud sql instances describe myapp-db \
  --format='value(settings.availabilityType, failoverReplica)'

Terraform HA Configuration

hcl
resource "google_sql_database_instance" "main" {
  name             = "myapp-db"
  database_version = "POSTGRES_16"
  region           = "us-central1"
  project          = var.project_id

  settings {
    tier              = "db-custom-4-16384"
    availability_type = "REGIONAL"
    disk_type         = "PD_SSD"
    disk_size         = 100
    disk_autoresize   = true

    backup_configuration {
      enabled                        = true
      start_time                     = "02:00"
      point_in_time_recovery_enabled = true
      transaction_log_retention_days = 7

      backup_retention_settings {
        retained_backups = 30
      }
    }

    maintenance_window {
      day          = 7  # Sunday
      hour         = 4
      update_track = "stable"
    }

    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.main.id
      require_ssl     = true
    }

    database_flags {
      name  = "max_connections"
      value = "200"
    }

    database_flags {
      name  = "log_min_duration_statement"
      value = "1000"
    }

    user_labels = {
      env  = "production"
      team = "backend"
    }
  }

  deletion_protection = true
}

Read Replicas

Read replicas provide horizontal read scaling by creating copies of your primary instance that serve read queries. Replicas use asynchronous replication, so there may be a small lag (typically under 1 second). You can create up to 10 read replicas per primary, including cross-region replicas for disaster recovery and low-latency global reads.

bash
# Create a read replica (same region)
gcloud sql instances create myapp-db-replica-1 \
  --master-instance-name=myapp-db \
  --tier=db-custom-4-16384 \
  --region=us-central1

# Create a cross-region read replica (for DR or low-latency reads)
gcloud sql instances create myapp-db-replica-eu \
  --master-instance-name=myapp-db \
  --tier=db-custom-4-16384 \
  --region=europe-west1

# Promote a replica to standalone (during DR)
gcloud sql instances promote-replica myapp-db-replica-eu

# Check replication lag
gcloud sql instances describe myapp-db-replica-1 \
  --format='value(replicaConfiguration.mysqlReplicaConfiguration)'

# For PostgreSQL, check lag from the replica:
# SELECT now() - pg_last_xact_replay_timestamp() AS replication_lag;

Cloud SQL Auth Proxy

The Cloud SQL Auth Proxy provides a secure way to connect to your Cloud SQL instance without exposing it to the public internet. It handles SSL encryption, IAM authentication, and connection management automatically. The proxy runs as a sidecar process alongside your application and creates a local Unix socket or TCP connection.

bash
# Download the Cloud SQL Auth Proxy
curl -o cloud-sql-proxy \
  https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.8.0/cloud-sql-proxy.linux.amd64
chmod +x cloud-sql-proxy

# Connect using instance connection name
./cloud-sql-proxy \
  --address 0.0.0.0 \
  --port 5432 \
  "PROJECT_ID:REGION:INSTANCE_NAME"

# Your app connects to localhost:5432 as if it were a local database
psql -h localhost -U app_user -d myapp

# In Kubernetes, run the proxy as a sidecar
# containers:
#   - name: app
#     image: myapp:latest
#     env:
#       - name: DB_HOST
#         value: "127.0.0.1"
#       - name: DB_PORT
#         value: "5432"
#   - name: cloud-sql-proxy
#     image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0
#     args:
#       - "--structured-logs"
#       - "--port=5432"
#       - "PROJECT:REGION:INSTANCE"
#     securityContext:
#       runAsNonRoot: true

Cloud SQL Connectors

Google provides language-specific Cloud SQL connectors for Python, Java, Go, and Node.js that eliminate the need for the proxy binary. These connectors handle IAM authentication and SSL internally, simplifying deployment. For example, the Python connector (cloud-sql-python-connector) integrates directly with SQLAlchemy.

IAM Database Authentication

Cloud SQL supports IAM authentication for PostgreSQL and MySQL, allowing you to use Google Cloud IAM identities instead of database passwords. This is more secure because it eliminates long-lived passwords, uses short-lived tokens, and integrates with IAM policies for centralized access management.

bash
# Enable IAM authentication on the instance
gcloud sql instances patch myapp-db \
  --database-flags=cloudsql.iam_authentication=on

# Create an IAM database user
gcloud sql users create user@company.com \
  --instance=myapp-db \
  --type=CLOUD_IAM_USER

# Create an IAM service account user
gcloud sql users create myapp-sa@project-id.iam.gserviceaccount.com \
  --instance=myapp-db \
  --type=CLOUD_IAM_SERVICE_ACCOUNT

# Grant database permissions (from psql)
# GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public
#   TO "user@company.com";

# Connect with IAM authentication
gcloud sql connect myapp-db --user=user@company.com --database=myapp

Private Connectivity

For production workloads, Cloud SQL instances should use private IP addresses instead of public IPs. Private IP connectivity uses VPC peering between your VPC and Google's service networking VPC. Traffic stays entirely within Google's network, eliminating exposure to the public internet.

bash
# Allocate an IP range for Google services
gcloud compute addresses create google-services-range \
  --global \
  --purpose=VPC_PEERING \
  --prefix-length=16 \
  --network=my-vpc

# Create private services access connection
gcloud services vpc-peerings connect \
  --service=servicenetworking.googleapis.com \
  --ranges=google-services-range \
  --network=my-vpc

# Create a Cloud SQL instance with private IP only
gcloud sql instances create myapp-db \
  --database-version=POSTGRES_16 \
  --tier=db-custom-4-16384 \
  --region=us-central1 \
  --network=projects/PROJECT/global/networks/my-vpc \
  --no-assign-ip \
  --availability-type=REGIONAL

Backup, Recovery, and Maintenance

bash
# View backup schedule
gcloud sql instances describe myapp-db \
  --format='value(settings.backupConfiguration)'

# Create an on-demand backup
gcloud sql backups create \
  --instance=myapp-db \
  --description="Pre-migration backup"

# List backups
gcloud sql backups list --instance=myapp-db \
  --format='table(id, windowStartTime, status, type)'

# Restore from backup
gcloud sql backups restore BACKUP_ID \
  --restore-instance=myapp-db

# Point-in-time recovery (PITR)
gcloud sql instances clone myapp-db myapp-db-pitr \
  --point-in-time="2026-03-14T10:00:00Z"

# Schedule maintenance window
gcloud sql instances patch myapp-db \
  --maintenance-window-day=SUN \
  --maintenance-window-hour=4 \
  --maintenance-release-channel=production

Performance Monitoring and Optimization

bash
# Enable Query Insights (performance monitoring)
gcloud sql instances patch myapp-db \
  --insights-config-query-insights-enabled \
  --insights-config-query-string-length=1024 \
  --insights-config-record-application-tags \
  --insights-config-record-client-address

# Check instance metrics
gcloud monitoring metrics list \
  --filter='metric.type = starts_with("cloudsql.googleapis.com")'

# Key metrics to monitor:
# cloudsql.googleapis.com/database/cpu/utilization
# cloudsql.googleapis.com/database/memory/utilization
# cloudsql.googleapis.com/database/disk/utilization
# cloudsql.googleapis.com/database/postgresql/num_backends
# cloudsql.googleapis.com/database/network/connections

# Create an alert for high CPU
gcloud alpha monitoring policies create \
  --display-name="Cloud SQL High CPU" \
  --condition-display-name="CPU > 80%" \
  --condition-filter='resource.type = "cloudsql_database" AND metric.type = "cloudsql.googleapis.com/database/cpu/utilization"' \
  --condition-threshold-value=0.8 \
  --condition-threshold-comparison=COMPARISON_GT \
  --condition-threshold-duration=300s \
  --notification-channels=CHANNEL_ID

Connection Limits

Cloud SQL has connection limits based on instance size (e.g., db-custom-1-3840 supports ~100 connections, db-custom-4-16384 supports ~400). Always use connection pooling (PgBouncer for PostgreSQL, ProxySQL for MySQL) or the Cloud SQL connector libraries which include built-in connection pooling. Exceeding the connection limit causes new connections to be rejected.

AlloyDB Guide: Next-Gen PostgreSQL on GCPFirestore Data Modeling Guide

Key Takeaways

  1. 1Regional HA provides 99.99% SLA with automatic failover in 60-120 seconds.
  2. 2Read replicas scale reads horizontally; cross-region replicas enable DR and low-latency global reads.
  3. 3Cloud SQL Auth Proxy provides secure connectivity without exposing instances to the public internet.
  4. 4IAM database authentication eliminates long-lived passwords using short-lived tokens.

Frequently Asked Questions

What is the difference between Cloud SQL and AlloyDB?
Cloud SQL runs standard MySQL/PostgreSQL engines with full compatibility. AlloyDB is a PostgreSQL-compatible database with a custom Google storage layer that provides 4x throughput and 100x faster analytical queries. Use Cloud SQL for standard workloads; AlloyDB for high-performance PostgreSQL needs.
How do I connect to Cloud SQL from Cloud Run?
Use the Cloud SQL Auth Proxy as a sidecar container or the Cloud SQL connector library. Both handle SSL and IAM authentication. Configure the Cloud Run service with the --add-cloudsql-instances flag for automatic proxy injection.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.