Google Cloud PostgreSQL for DBAs: The Cloud SQL Operating Model
Cloud SQL removes host and storage administration; it does not remove database engineering. The dangerous migration is the one that transfers PostgreSQL unchanged while leaving failover, connection recovery, and service limits untested.
Situation
A team moving PostgreSQL from Compute Engine already knows how to tune SQL and operate backups. Cloud SQL takes responsibility for VM lifecycle, supported engine maintenance, storage management, and managed availability. The application still owns connection behavior, transaction retries, query design, capacity planning, and recovery validation.
That boundary matters because Cloud SQL is a service contract, not a VM with root access. DBAs cannot install arbitrary host software, replace the storage subsystem, or assume that a setting accepted by self-managed PostgreSQL is configurable in the service.
The Problem
The most common design error is to reduce the migration decision to “PostgreSQL is PostgreSQL.” SQL compatibility does not make the operating model identical. A zonal instance has a different failure boundary from a regional HA instance. A read replica is not an HA standby. The Cloud SQL Auth Proxy authenticates and encrypts connections, but it is not a connection pool. A maintenance event or failover terminates existing sessions even when the endpoint remains stable.
The architectural question is therefore: which responsibilities moved to Google, which remained with the workload, and how will the team prove the boundary under failure?
The Managed-Service Boundary
flowchart TD
App[Application] --> Pool[Application connection pool]
Pool --> Connector[Cloud SQL connector or Auth Proxy]
Connector --> Endpoint[Cloud SQL instance endpoint]
Endpoint --> Primary[Primary — zone A]
Primary --> PrimaryDisk[(Persistent disk — zone A)]
Primary -->|Synchronous write| StandbyDisk[(Persistent disk — zone B)]
StandbyDisk --> Standby[Standby — zone B]
Primary --> Replica[Optional read replica]
For a regional HA instance, Google runs a primary and standby in different zones and synchronously replicates writes to regional persistent disk. The standby is not an application-readable replica. If the primary becomes unresponsive, Cloud SQL can fail over and retain the instance connection name and IP address; existing connections still close and must reconnect. Google documents that reconnection is typically possible in about 60 seconds, but that is an observation to test, not an application SLA to hard-code.
Read replicas solve a different problem. They serve read traffic and use asynchronous replication, so they can lag and return stale results. Cross-region replicas can form part of disaster recovery, but promotion is an explicit recovery action and produces a new primary endpoint.
The connectivity layer also has a precise boundary. Cloud SQL connectors and the Auth Proxy provide IAM-aware authorization and TLS without requiring the application to manage certificates. They do not restrict the number of PostgreSQL backends. The application still needs a bounded pool, timeouts, retry policy, and admission control. PgBouncer is one possible pooler, but it is an additional component with its own failure and transaction-pooling semantics.
Document the boundary in the service ownership map: Google owns the managed host and control plane; the platform team owns network and IAM policy; the database team owns schemas and capacity; and the application team owns transaction semantics, pooling, and retries. Ambiguous ownership is itself a failure mode during an outage.
In Practice
Define the instance declaratively, but keep environment-specific sizing out of a reusable example:
resource "google_sql_database_instance" "postgres" {
name = "production-postgres"
database_version = "POSTGRES_15"
region = "us-central1"
deletion_protection = true
settings {
tier = "db-custom-8-32768"
availability_type = "REGIONAL"
disk_type = "PD_SSD"
disk_autoresize = true
backup_configuration {
enabled = true
point_in_time_recovery_enabled = true
start_time = "03:00"
}
maintenance_window {
day = 7
hour = 4
update_track = "stable"
}
}
}
This configuration is a starting point, not proof of readiness. Pin the provider version, review the selected PostgreSQL version’s support policy, validate the tier in the target region, and plan how Terraform state and deletion protection are controlled.
The CARL evidence here is system behavior documented by Google: regional HA closes sessions during failover; maintenance can interrupt connectivity; replicas can lag; and connectors are not poolers. Convert those behaviors into tests:
- Trigger a manual failover under representative traffic and measure reconnect time, retry volume, and tail latency.
- Exhaust the configured application pool in staging and verify load is rejected rather than expanding unbounded connections.
- Measure replica lag and test a read-after-write request against the replica path.
- Restore a backup or PITR copy and verify application-level integrity, not merely instance creation.
Where It Breaks
| Failure mode | Evidence to inspect | Engineering response |
|---|---|---|
| Connection storm after failover | Backend count, pool queue depth, retry rate | Add jittered retry, cap pools, and avoid every process reconnecting simultaneously. |
| Storage saturation | Read and write latency, throughput, queue depth | Tune queries first; then size storage and compute from measured demand. Do not prescribe an arbitrary disk size. |
| Stale replica reads | Replica lag and application consistency errors | Route read-after-write and correctness-sensitive queries to the primary. |
| Maintenance surprise | Maintenance event logs and client disconnects | Configure windows and deny periods where appropriate; make disconnect recovery routine. |
| Terraform destroys or replaces an instance | Plan output and state history | Require reviewed plans, deletion protection, backups, and a tested recovery path. |
What to Do Next
- Problem: The team has transferred the database but not redesigned around the managed-service failure boundary.
- Solution: Treat HA, connection management, read scaling, and recovery as separate capabilities with separate tests.
- Proof: Google’s documented HA behavior explicitly closes existing connections while retaining the endpoint, and replicas explicitly permit lag.
- Action: Run a failover and restore exercise before production cutover, recording measured RTO, observed RPO, retry behavior, and pool saturation.