# Cloud SQL Terraform: Infrastructure as Code Guide for Private PostgreSQL Deployment

> Automate private PostgreSQL deployments with Cloud SQL Terraform. Learn to use Infrastructure as Code for secure, declarative configurations, private networking, and IAM authentication.

- Repository: [Google/skills](https://github.com/google/skills)
- Tags: how-to-guide
- Published: 2026-08-15

---

**Cloud SQL Terraform enables fully automated, private PostgreSQL deployments using Private Service Connect, IAM authentication, and declarative HCL configuration.**

Google Cloud SQL provides a fully-managed relational database service that you can provision entirely through Terraform infrastructure as code. By describing your desired database state in HashiCorp Configuration Language (HCL), you obtain reproducible, version-controlled infrastructure deployable across environments without manual console work.

---

## Core Architecture Components

The Google Skills repository demonstrates a production-grade Cloud SQL Terraform module built around five key components.

### Cloud SQL Instance Resource

The `google_sql_database_instance` resource defines the database engine and connectivity model. According to `assets/main.tf` in the N-Tier Serverless Web App skill, production deployments should enable **Private Service Connect** (`psc_enabled = true`) and explicitly disable public IP access (`ipv4_enabled = false`).

Key settings include:
- `database_version` – e.g., `"POSTGRES_18"` for PostgreSQL 18 Enterprise
- `availability_type` – `"REGIONAL"` for high availability across zones
- `tier` – machine type such as `"db-custom-2-7680"`

### PSC Forwarding Rule

Private Service Connect requires a `google_compute_forwarding_rule` that maps a reserved internal IP to the Cloud SQL service attachment. This keeps all database traffic inside your VPC without traversing the public internet.

### IAM-Authenticated Database Users

The `google_sql_user` resource with `type = "CLOUD_IAM_USER"` eliminates password management. Users authenticate through Google's IAM system and connect via the Cloud SQL Auth Proxy.

### Service Account Permissions

Applications receive database access through `google_project_iam_member` bindings granting `roles/cloudsql.client`. This follows least-privilege principles documented in [`references/iam-security.md`](https://github.com/google/skills/blob/main/references/iam-security.md).

### Optional Monitoring Configuration

The `insights_config` block within `google_sql_database_instance` enables **Query Insights** for performance analysis without additional agents.

---

## Complete Terraform Configuration Example

This production-ready snippet from `assets/main.tf` provisions a private PostgreSQL instance with IAM authentication and Query Insights:

```hcl
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

# -------------------------------------------------------------------------

# Cloud SQL instance (Private Service Connect, no public IP)

# -------------------------------------------------------------------------

resource "google_sql_database_instance" "postgres" {
  name                = var.instance_name
  database_version    = "POSTGRES_18"
  region              = var.region
  tier                = var.instance_tier
  deletion_protection = true

  settings {
    tier              = var.instance_tier
    activation_policy = "ALWAYS"
    availability_type = "REGIONAL"

    ip_configuration {
      ipv4_enabled = false
      psc_config {
        psc_enabled = true
      }
    }

    insights_config {
      query_insights_enabled = true
    }
  }
}

# -------------------------------------------------------------------------

# PSC forwarding rule (private IP in consumer VPC)

# -------------------------------------------------------------------------

resource "google_compute_forwarding_rule" "psc_sql" {
  name                  = "${var.instance_name}-psc"
  region                = var.region
  load_balancing_scheme = "INTERNAL"
  network               = var.vpc_network
  ip_address            = var.psc_ip
  target                = google_sql_database_instance.postgres.service_attachment_self_link
  ports                 = ["5432"]
}

# -------------------------------------------------------------------------

# IAM binding for application service account

# -------------------------------------------------------------------------

resource "google_project_iam_member" "sql_client" {
  project = var.project_id
  role    = "roles/cloudsql.client"
  member  = "serviceAccount:${var.backend_service_account}"
}

# -------------------------------------------------------------------------

# Database and IAM-authenticated user

# -------------------------------------------------------------------------

resource "google_sql_database" "app_db" {
  name     = var.database_name
  instance = google_sql_database_instance.postgres.name
}

resource "google_sql_user" "app_user" {
  name     = var.db_user
  instance = google_sql_database_instance.postgres.name
  type     = "CLOUD_IAM_USER"
}

```

---

## Deployment Workflow

Execute these steps to deploy your Cloud SQL Terraform configuration:

1. **Initialize Terraform** – Download providers and modules:

```bash
terraform init

```

2. **Validate configuration** – Catch syntax errors before any infrastructure changes:

```bash
terraform validate

```

3. **Plan changes** – Review the execution plan with a dry-run:

```bash
terraform plan -out=tfplan

```

4. **Apply configuration** – Provision resources after plan review:

```bash
terraform apply tfplan

```

---

## Application Connectivity: Cloud SQL Auth Proxy

Cloud SQL Terraform pairs with the Cloud SQL Auth Proxy for secure, passwordless connections. In your Cloud Run service configuration, mount the proxy's Unix socket:

```yaml
containers:
- name: app
  image: gcr.io/${PROJECT_ID}/my-app:latest
  volumeMounts:
  - name: cloudsql-instance
    mountPath: /cloudsql
volumes:
- name: cloudsql-instance
  cloudSqlInstance:
    instances: ["${PROJECT_ID}:${REGION}:${INSTANCE_NAME}"]

```

Your application connects through the socket path `/cloudsql/${PROJECT_ID}:${REGION}:${INSTANCE_NAME}` using IAM authentication—no passwords stored or transmitted.

---

## Security Best Practices from the Source Code

The `google/skills` repository enforces several hardening patterns for Cloud SQL Terraform deployments:

| Practice | Implementation |
|----------|---------------|
| **No public IP exposure** | `ipv4_enabled = false` in `ip_configuration` block |
| **Private connectivity only** | `psc_enabled = true` with PSC forwarding rule |
| **Least-privilege networking** | Firewall rules allowing only TCP 5432 to PSC endpoint and TCP 443 for Auth Proxy token exchange |
| **IAM-based authentication** | `type = "CLOUD_IAM_USER"` instead of built-in database passwords |
| **Deletion protection** | `deletion_protection = true` to prevent accidental instance destruction |

These patterns appear in [`SKILL.md`](https://github.com/google/skills/blob/main/SKILL.md) and `assets/main.tf` within the N-Tier Serverless Web App skill directory.

---

## Key Reference Files

| File | Location | Purpose |
|------|----------|---------|
| [`SKILL.md`](https://github.com/google/skills/blob/main/SKILL.md) | [`skills/cloud/google-cloud-solution-n-tier-serverless-web-app/SKILL.md`](https://github.com/google/skills/blob/main/skills/cloud/google-cloud-solution-n-tier-serverless-web-app/SKILL.md) | Architecture overview and Cloud SQL IaC patterns |
| `assets/main.tf` | `skills/cloud/google-cloud-solution-n-tier-serverless-web-app/assets/main.tf` | Complete Terraform module implementation |
| [`references/terraform-usage.md`](https://github.com/google/skills/blob/main/references/terraform-usage.md) | [`skills/cloud/spanner-basics/references/terraform-usage.md`](https://github.com/google/skills/blob/main/skills/cloud/spanner-basics/references/terraform-usage.md) | General Terraform style guide for extending modules |
| [`references/iam-security.md`](https://github.com/google/skills/blob/main/references/iam-security.md) | [`skills/cloud/workload-manager-basics/references/iam-security.md`](https://github.com/google/skills/blob/main/skills/cloud/workload-manager-basics/references/iam-security.md) | IAM authentication best practices |
| [`references/general-best-practices.md`](https://github.com/google/skills/blob/main/references/general-best-practices.md) | [`skills/cloud/workload-manager-basics/references/general-best-practices.md`](https://github.com/google/skills/blob/main/skills/cloud/workload-manager-basics/references/general-best-practices.md) | Cloud-native security principles |

---

## Summary

- **Cloud SQL Terraform** enables fully declarative database provisioning through HCL configuration files tracked in version control
- **Private Service Connect** with disabled public IP provides secure, VPC-native connectivity without internet exposure
- **IAM database authentication** eliminates password management and integrates with Google Cloud's identity system
- **Query Insights** offers built-in performance monitoring through the `insights_config` block
- The `google/skills` repository provides production-tested modules at `assets/main.tf` with security hardening patterns documented in [`SKILL.md`](https://github.com/google/skills/blob/main/SKILL.md)

---

## Frequently Asked Questions

### What is the difference between Private Service Connect and private IP for Cloud SQL?

Private Service Connect establishes a **private, consumer-side endpoint** that routes traffic through Google's network backbone without exposing IPs publicly. Traditional private IP requires VPC peering and allocates IP addresses from your VPC range. PSC offers simpler routing, better security boundaries, and is the recommended approach in the `google/skills` Cloud SQL Terraform modules.

### How does IAM database authentication work with Terraform-managed Cloud SQL?

Set `type = "CLOUD_IAM_USER"` in the `google_sql_user` resource. Users authenticate with OAuth 2.0 tokens instead of passwords, and the Cloud SQL Auth Proxy validates these tokens automatically. Your Terraform configuration grants `roles/cloudsql.client` to service accounts, enabling applications to connect without credential files.

### Can I enable high availability through Cloud SQL Terraform?

Yes. Set `availability_type = "REGIONAL"` in the `settings` block of `google_sql_database_instance`. This creates a synchronous standby in a different zone within the same region, providing automatic failover without data loss. The configuration in `assets/main.tf` demonstrates this pattern combined with deletion protection for production safety.

### Should I use `terraform.tfvars` or environment variables for sensitive values?

Use **environment variables prefixed with `TF_VAR_`** for sensitive values like project IDs and service account emails, or integrate with Google Secret Manager via the `google_secret_manager_secret_version` data source. Never commit credentials to `terraform.tfvars` in version control. The [`references/terraform-usage.md`](https://github.com/google/skills/blob/main/references/terraform-usage.md) file shows variable passing patterns compatible with Cloud Shell and CI/CD pipelines.