PostgreSQL on Cloud SQL: Managed PostgreSQL in GCP
PostgreSQL on Cloud SQL is Google’s managed PostgreSQL service. You get a real PostgreSQL database (same engine, same SQL, same drivers) without managing servers, storage, or backups. Google handles patching, failover, and maintenance; you focus on your schema and your application.
This page covers what PostgreSQL on Cloud SQL is, how to set it up, and the specific behaviours that differ from self-managed PostgreSQL: the permission model, extension support, database flags, and a few version-specific details that catch people out in production. For connection security (Auth Proxy, private IP, IAM auth), see Connecting to Cloud SQL Securely.
What is PostgreSQL on Cloud SQL?
Cloud SQL is GCP’s managed relational database service. It runs MySQL, PostgreSQL, and SQL Server on Google-managed infrastructure. When you create a PostgreSQL instance, you get a real PostgreSQL database running on a Google-managed virtual machine in the region you choose.
The key difference from a self-hosted setup is what you no longer have to do. You do not install the database software, manage OS patches, configure storage, set up backups, or wire together high availability. Google handles all of that. What you still manage is your schema, your data, your users, and how your application connects.
Think of it like the difference between leasing a car and buying one. With a lease, someone else handles servicing, depreciation, and compliance checks. You just drive. With Cloud SQL, Google handles the server, the OS, the backups, and the patching. You just write SQL. You give up some customisation, but you gain back a lot of time.
For a broader overview of Cloud SQL across all three engines, see Cloud SQL Overview. If you are deciding which GCP database fits your workload, see Choosing the Right Storage Service.
How PostgreSQL on Cloud SQL works
A Cloud SQL instance is a virtual machine running PostgreSQL, managed by
Google. You choose the machine type (which controls CPU and memory), the
storage type and size, and the region. Google manages the hypervisor, operating
system, and PostgreSQL installation. You interact with the database using the
same tools you would use with any PostgreSQL server: psql,
application ORMs, database GUIs.
Storage grows automatically if you enable the option. Automated backups run on the schedule you configure. Point-in-time recovery (PITR) is built on PostgreSQL’s write-ahead log (WAL): when backups are enabled, PITR is available automatically with no extra flags. This is simpler than MySQL, which requires separate binary log configuration. For more on backup and recovery options, see Backups and High Availability.
Connections from your application reach Cloud SQL through one of three patterns: the Cloud SQL Auth Proxy (recommended for most cases), private IP within a VPC, or public IP with an authorised networks allowlist. The Auth Proxy handles TLS and IAM authentication, so you do not need to manage SSL certificates or open broad firewall rules. For full connection guidance, see Connecting to Cloud SQL Securely.
High availability is an optional add-on. When enabled, Cloud SQL maintains a standby instance in a different zone within the same region. Failover is automatic if the primary fails. You can also add read replicas for read-heavy workloads.
Two things work differently from self-managed PostgreSQL: you cannot edit
postgresql.conf directly (server configuration goes through
Cloud SQL database flags), and the postgres user has restricted
privileges rather than full superuser access. Both are covered below.
Creating a PostgreSQL instance
Use gcloud sql instances create to create a new instance. The
flags below represent a sensible baseline for a production workload: SSD
storage, automatic storage growth, and automated backups.
# Create a PostgreSQL 15 instance with backups enabled
gcloud sql instances create my-postgres-instance \
--database-version=POSTGRES_15 \
--tier=db-n1-standard-2 \
--region=europe-west2 \
--storage-type=SSD \
--storage-size=20GB \
--storage-auto-increase \
--backup-start-time=02:00PITR is enabled automatically when backups are on. PostgreSQL uses WAL archiving rather than binary logging, so no separate flag is needed.
Cloud SQL does not offer db-f1-micro for PostgreSQL 15 and
later. The smallest available tier for development is
db-g1-small. For production, choose a tier based on your
expected connection count and query workload, not just storage size.
After creating the instance, create a database for your application:
# Create an application database
gcloud sql databases create my-app-db \
--instance=my-postgres-instanceUsers, roles, and permissions
Cloud SQL creates a default user called postgres. On a
self-managed instance this user is a full superuser. On Cloud SQL,
postgres is a member of the cloudsqlsuperuser
role, which has broad privileges but not unrestricted ones. Operations
that require genuine superuser access, such as loading server-side extensions
not on the approved list, are blocked.
Think of postgres on Cloud SQL like a senior employee
who has access to most rooms in the building. They can do almost
everything. But a few doors (the server room, the electrical panel)
require the facilities manager (Google) to open. You hand over
control of those rooms in exchange for not having to maintain them.
This restriction is by design. It lets Google run the managed service reliably without allowing tenants to break the underlying infrastructure. In practice you will rarely hit the limit unless you are migrating a workload that depended on OS-level PostgreSQL features.
For your application, create a dedicated user with only the privileges it
needs. Do not connect as postgres. PostgreSQL’s permission
model is more granular than MySQL’s: you grant database-level,
schema-level, and object-level permissions separately.
# Set the postgres user password
gcloud sql users set-password postgres \
--instance=my-postgres-instance \
--password=your-secure-password
# Create a dedicated application user
gcloud sql users create app-user \
--instance=my-postgres-instance \
--password=app-user-passwordOnce connected via psql or the Auth Proxy, grant the application
user access at each level:
-- Grant connection rights to the database
GRANT CONNECT ON DATABASE my-app-db TO "app-user";
-- Grant usage rights on the schema
GRANT USAGE ON SCHEMA public TO "app-user";
-- Grant access to all existing tables
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "app-user";The last grant covers existing tables but not tables created later, for example by application migrations. Set default privileges to handle future tables automatically:
-- Grant permissions on tables created in the future
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "app-user";Store your database password in Secret Manager rather than hardcoding it in environment variables or deployment configuration. This keeps credentials out of your codebase and makes rotation straightforward.
Schemas and the PostgreSQL 15 public schema change
PostgreSQL 15 changed the default permissions on the public
schema. Before PostgreSQL 15, every user had the CREATE
privilege on the public schema by default. In PostgreSQL 15 and later, that
default was revoked. If your application user needs to create tables (which
includes running migrations), you must grant this explicitly.
-- PostgreSQL 15+: grant schema creation to the application user
GRANT CREATE ON SCHEMA public TO "app-user";
-- Alternatively, create a dedicated application schema
CREATE SCHEMA myapp AUTHORIZATION "app-user";An application that worked on PostgreSQL 14 or earlier will fail with a
permission denied error when running migrations against a new
PostgreSQL 15 instance. This is one of the most common surprise failures
when upgrading. Check this early, before your first deployment.
PostgreSQL extensions in Cloud SQL
PostgreSQL extensions add functionality to the database: UUID generation, text
search, geographic data types, cryptography, and more. You install them
per-database with CREATE EXTENSION.
Cloud SQL supports a curated list of extensions. Common ones including
pgcrypto, uuid-ossp, PostGIS,
pg_trgm, and hstore are available. Extensions that
require OS-level access or genuine superuser operations are not. Before
building a schema that depends on a specific extension, verify it is on the
Cloud SQL supported extensions list. Discovering a missing extension during a
migration is an expensive problem.
-- Enable UUID generation
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Enable trigram indexing for fast text search
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- Enable PostGIS for geographic data
CREATE EXTENSION IF NOT EXISTS postgis;
-- List currently installed extensions
SELECT extname, extversion FROM pg_extension;Some extensions (including PostGIS) must be enabled by a
cloudsqlsuperuser member before an unprivileged user can use
them. If CREATE EXTENSION fails with a permission error,
connect as postgres and run it there first.
Configuring PostgreSQL with database flags
On a self-managed PostgreSQL server you edit postgresql.conf to
tune memory, connections, and logging. On Cloud SQL, that file is managed by
Google and not directly editable. Instead, you set configuration through Cloud
SQL database flags, which map directly to PostgreSQL server parameters and are
applied via gcloud sql instances patch.
Database flags are like the settings app on a smartphone. You can adjust everything the manufacturer exposes to you: display brightness, notification behaviour, power settings. But you cannot open the phone and resolder a component. A self-managed PostgreSQL server is like having the full schematic. Cloud SQL gives you the settings app. For most use cases, the settings app is enough.
# Increase the maximum number of connections
gcloud sql instances patch my-postgres-instance \
--database-flags=max_connections=200
# Log queries taking longer than 500ms (helps identify slow queries)
gcloud sql instances patch my-postgres-instance \
--database-flags=log_min_duration_statement=500
# Enable logical decoding for CDC tools like Debezium
gcloud sql instances patch my-postgres-instance \
--database-flags=cloudsql.logical_decoding=on
# View currently configured flags
gcloud sql instances describe my-postgres-instance \
--format="value(settings.databaseFlags)"Some flag changes require a restart. The gcloud response includes a
requiresRestart field when a restart is needed. Schedule these
during a maintenance window for production instances.
Each PostgreSQL connection holds several MB of RAM. Setting
max_connections too high on a small instance can exhaust
memory under load. For applications with many concurrent connections, use
a connection pooler like PgBouncer in front of Cloud SQL and keep
max_connections at a level the instance tier can actually
support.
Importing and exporting data
# Export a database to Cloud Storage as a SQL dump
gcloud sql export sql my-postgres-instance \
gs://my-backup-bucket/my-app-db-export.sql \
--database=my-app-db
# Import a SQL dump from Cloud Storage
gcloud sql import sql my-postgres-instance \
gs://my-backup-bucket/my-app-db-export.sql \
--database=my-app-db
# Export a single table as CSV
gcloud sql export csv my-postgres-instance \
gs://my-backup-bucket/my-table.csv \
--database=my-app-db \
--query="SELECT * FROM my_table"The Cloud SQL service account needs roles/storage.objectAdmin on
the target bucket, or at minimum storage.objectCreate for exports
and storage.objectGet for imports.
Large imports run as long-running operations and do not block the instance. For very large databases or minimal-downtime migrations from an external PostgreSQL system, Database Migration Service (DMS) uses continuous replication to cut over with only seconds of downtime.
When to use PostgreSQL on Cloud SQL
PostgreSQL on Cloud SQL is a strong fit for:
- Transactional web and mobile applications that need ACID guarantees, relational data, and SQL joins
- Teams migrating an existing PostgreSQL workload to GCP without rewriting application code or queries
- Applications that use PostgreSQL-specific features such as PostGIS for geographic data,
pg_trgmfor text search, or JSONB for semi-structured data - Internal tools and admin systems where predictable, consistent query behaviour matters more than horizontal scale
- Teams that want managed operations (automated backups, HA failover, version patching) without running a database server
PostgreSQL on Cloud SQL may not be the right choice when:
- You need globally distributed writes across multiple regions. Cloud Spanner is designed for that workload.
- Your data is document-structured and schema-free. Firestore may fit better; see Cloud SQL vs Firestore.
- Your workload is primarily analytical. Large scans and aggregations across billions of rows are better handled by BigQuery.
- You need full superuser access, custom OS-level extensions, or configuration options not exposed through database flags.
PostgreSQL vs MySQL on Cloud SQL
Both engines run on the same Cloud SQL infrastructure with the same management model: same backup system, same connection options, same flag-based configuration. The differences are in the database engines themselves.
| PostgreSQL | MySQL | |
|---|---|---|
| Data types | Richer: arrays, JSONB, ranges, custom types | Simpler: JSON supported, fewer native types |
| Extension ecosystem | Extensive: PostGIS, pg_trgm, pgcrypto, hstore, and more | Limited extension support |
| SQL compliance | Strict and standards-compliant | Historically more permissive with non-standard SQL |
| PITR mechanism | WAL archiving, automatic when backups are enabled | Requires —enable-bin-log flag at creation |
| Public schema (v15+) | CREATE on public schema must be granted explicitly | Not applicable |
| Common use cases | Complex schemas, GIS, text search, migrations from PostgreSQL | LAMP stack apps, existing MySQL workloads, simple schemas |
If you are starting from scratch, both engines are reasonable choices for most web applications. PostgreSQL is generally preferred when you need complex data types, richer extensions, or strict SQL behaviour. MySQL is often simpler to set up for straightforward web workloads. For MySQL-specific setup, see Running MySQL on Cloud SQL.
Cloud SQL for PostgreSQL vs self-managed PostgreSQL
Running PostgreSQL on a Compute Engine VM gives you more control at the cost of more responsibility. Here is how the two compare:
Operational overhead: Self-managed requires you to handle OS patching, database upgrades, backup configuration, and HA setup. Cloud SQL handles all of that automatically.
Superuser access: Self-managed gives you full
postgressuperuser access. Cloud SQL restricts it tocloudsqlsuperuser. Most applications are unaffected; workloads that need OS-level access or unsupported extensions are not.Configuration: Self-managed lets you edit
postgresql.confandpg_hba.confdirectly. Cloud SQL uses database flags, which cover most tuning needs but not every edge case.Extension availability: Self-managed lets you install any extension. Cloud SQL only supports its curated list.
Cost: Cloud SQL instances carry managed service overhead. Self-managed VMs are cheaper per CPU-hour but require engineering time to run reliably, which typically costs more in practice.
For most teams building applications on GCP, Cloud SQL is the right default. Self-managed PostgreSQL on Compute Engine makes sense when you have very specific configuration requirements, need extensions Cloud SQL does not support, or are running a cost-sensitive workload where the operational investment is justified.
Common mistakes
Assuming the postgres user has full superuser access. The
postgresuser on Cloud SQL is more restricted than on a self-managed instance. Operations like loading unsupported extensions or modifying replication settings directly are unavailable. Plan your permission model aroundcloudsqlsuperuserfrom the start.Forgetting default privileges for future tables. Granting access to existing tables but not to future ones means your application fails when a migration creates a new table. Use
ALTER DEFAULT PRIVILEGESso tables added later are automatically accessible to the application user.Not handling the PostgreSQL 15 public schema change. Applications that worked on PostgreSQL 14 or earlier will get a
permission deniederror when running migrations on a new PostgreSQL 15 instance. Explicitly grantCREATEon the public schema or create a dedicated application schema.Setting max_connections too high without a connection pooler. Each PostgreSQL connection holds several MB of RAM. Setting
max_connections=500on a small instance can exhaust memory under load. Use PgBouncer for high-connection workloads and size connections to match the instance tier.Depending on an extension without verifying it is supported. Not every PostgreSQL extension is available in Cloud SQL. Verify an extension is on the supported list before designing a schema that depends on it. Discovering a missing extension during a migration is far more expensive than finding out during planning. If you hit connection problems after setup, see Cloud SQL Connection Refused for troubleshooting steps.
Frequently asked questions
What is PostgreSQL on Cloud SQL?
PostgreSQL on Cloud SQL is Google’s managed PostgreSQL database service. It runs a real PostgreSQL engine, but Google manages the underlying infrastructure: the virtual machine, OS patches, backups, storage, and high availability. You interact with it using standard PostgreSQL tools and application drivers.
Is Cloud SQL PostgreSQL the same as regular PostgreSQL?
For application code, yes. The same SQL, the same drivers, the same query
behaviour. The differences are operational: you cannot edit
postgresql.conf directly, the postgres user has
restricted superuser access, and only supported extensions can be installed.
The vast majority of applications run without any changes.
Does Cloud SQL give full superuser access?
No. The postgres user is a member of the
cloudsqlsuperuser role, which has broad but restricted privileges.
Genuine superuser operations (loading server-side extensions not on the
approved list, modifying replication internals) are blocked. This is a
deliberate constraint of the managed service.
Which PostgreSQL extensions are supported in Cloud SQL?
Cloud SQL supports a curated list that includes many common extensions:
pgcrypto, uuid-ossp, PostGIS,
pg_trgm, hstore, and others. Extensions that require
OS-level access or unrestricted superuser operations are not supported. Check
the Cloud SQL extensions documentation before your project depends on a
specific one.
When should I choose PostgreSQL instead of MySQL in Cloud SQL?
Choose PostgreSQL when your application uses complex data types (arrays, JSONB, custom types), geographic data via PostGIS, or depends on strict SQL compliance. Choose PostgreSQL if you are migrating from an existing PostgreSQL system. If you are starting fresh with a straightforward web app schema, either engine works well and the choice often comes down to team familiarity.
Summary
- PostgreSQL on Cloud SQL is managed PostgreSQL: real engine, no server management, with Google handling backups, patching, and HA
- Use PostgreSQL 15 or 16 for new instances; PITR is automatic via WAL archiving when backups are enabled, with no separate flag needed
- The
postgresuser has restricted superuser access; design permissions aroundcloudsqlsuperuserfrom the start - Configure server settings through Cloud SQL database flags, not
postgresql.conf - Extensions are supported from a curated list; verify availability before your design depends on one
- PostgreSQL 15 revoked public schema
CREATEby default; grant it explicitly or use a dedicated application schema - Use
ALTER DEFAULT PRIVILEGESso tables created by future migrations are automatically accessible to your application user - Use a connection pooler like PgBouncer for high-connection workloads and size
max_connectionsto match the instance tier
Frequently asked questions
What PostgreSQL versions does Cloud SQL support?
Cloud SQL supports PostgreSQL 12, 13, 14, 15, and 16. Use version 15 or 16 for new instances. Older versions such as 9.6 and 10 are deprecated and no longer available for new instances. Check the Cloud SQL documentation for the current supported list, as minor versions are updated regularly.
Is Cloud SQL PostgreSQL the same as regular PostgreSQL?
It runs the same PostgreSQL engine, so your SQL, application drivers, and most tools work without changes. The differences are operational: the postgres user has restricted privileges, you configure server settings through database flags instead of postgresql.conf, and only supported extensions can be installed. For most applications, these constraints are invisible.
Can I use pg_dump to export data from Cloud SQL PostgreSQL?
Yes. Connect via the Cloud SQL Auth Proxy and run pg_dump from your local machine or a Compute Engine VM. Cloud SQL also supports exporting directly to Cloud Storage using gcloud sql export sql, which creates a pg_dump-compatible file without impacting the running instance. For very large databases, Database Migration Service is a better option.
Does Cloud SQL for PostgreSQL support logical replication?
Yes. Enable logical replication by setting the cloudsql.logical_decoding flag to on. This allows external tools like Debezium to read the write-ahead log (WAL) for change data capture. External read replicas using logical replication are also supported for migration scenarios.