Cloud SQL for MySQL: Setup, Security, and Production Patterns

Cloud SQL for MySQL is Google’s managed database service for MySQL workloads. You get a real MySQL instance where your schemas, queries, and drivers work exactly as expected. What changes is everything underneath: Google manages the server, storage, patches, backups, and failover. You focus on your database, not the infrastructure running it.

This page covers MySQL-specific behaviour on Cloud SQL: how the managed service model works, when it is the right choice, how to create and configure an instance, manage users securely, and connect from your application. For a broader overview of Cloud SQL, see Cloud SQL Overview. For connection security in depth, see Connecting to Cloud SQL Securely.

What Cloud SQL for MySQL really is

If you have used MySQL before, Cloud SQL will feel familiar almost immediately. You connect with the same client, write the same SQL, and manage schemas the same way. The MySQL engine is genuine, not emulated.

Analogy

Think of Cloud SQL like renting space in a managed data centre rather than running your own server room. You bring your application and your data. The landlord handles the power, cooling, hardware replacement, and security doors. You still decide what goes in your room and who has the key. What you cannot do is knock a hole in the wall or rewire the fuse box yourself.

The managed part means Google handles: provisioning the underlying VM, applying OS and database patches, running automated backups, managing storage growth, and responding to hardware failures. You never SSH into the database server, and you never edit my.cnf directly. Database flags are how you tune the server.

What you still manage: your schemas, users, data, access permissions, connection handling, and query performance. The managed service draws a line at the database engine itself. Everything above that line is your responsibility.

SUPER privilege

Cloud SQL restricts the SUPER privilege. You cannot run arbitrary SUPER-level SQL at runtime. When you need to change a global server variable, you do it through Cloud SQL database flags rather than a SET GLOBAL statement. Most workloads never hit this restriction, but it matters when migrating from a self-managed instance that relied on it.

How Cloud SQL for MySQL works

A Cloud SQL instance is a managed VM running the MySQL process. You choose the machine type (CPU and RAM), storage size and type, the region, and whether you want high availability. Cloud SQL provisions the VM, attaches the storage, installs the correct MySQL version, and makes it accessible according to your connection settings.

Storage is separate from the VM and can grow automatically when you enable storage auto-increase. Daily automated backups are stored in Cloud Storage. Point-in-time recovery (PITR) builds on those backups using continuous binary logs, which lets you restore to any second within the retention window. Binary logging must be explicitly enabled at instance creation.

Two separate concerns

Connecting to Cloud SQL involves two independent questions: network path (how traffic reaches the instance physically) and authentication (how the client proves its identity). Beginners often conflate these. Private IP, the Auth Proxy, and public IP allowlists are all network path choices. IAM database auth and native passwords are authentication choices. You combine one from each column.

Read replicas stream changes from the primary continuously and can handle read-heavy queries, but they do not provide automatic failover. A high-availability instance uses a synchronous standby in a different zone and fails over automatically if the primary zone has a problem.

Analogy: replicas vs HA

A read replica is like a photocopier running constantly in the background. It keeps a current copy of everything, and you can read from it freely. But if the original machine breaks, the photocopier cannot become the original on its own. High availability is like having a trained backup operator who takes over the moment the primary goes down, with no action required from you.

When to use Cloud SQL for MySQL

Cloud SQL for MySQL fits well when your data is relational, your access patterns involve SQL queries, and you want a managed service rather than running a database server yourself. Good fits include:

  • Web applications with a relational data model. User accounts, orders, products, sessions, content: anything that maps naturally to tables with relationships is a reasonable fit. If your ORM or framework expects MySQL, Cloud SQL is the lowest-friction path.

  • Migrating an existing MySQL application. Your schema, queries, and application code all transfer with minimal changes. Cloud SQL is designed to be compatible with standard MySQL, so most migrations involve configuration changes rather than application rewrites.

  • Teams that want managed database operations. If you do not have a dedicated DBA and do not want to manage patching, backups, and failover manually, the managed model is a meaningful advantage over running MySQL yourself on a VM.

  • Transactional workloads. If your workload depends on ACID transactions, foreign key constraints, or complex multi-table queries, Cloud SQL is the right service in the GCP storage family. Firestore, BigQuery, and Bigtable serve different patterns.

  • Applications running on Cloud Run or GKE. Cloud Run integrates with Cloud SQL via the Auth Proxy sidecar, making it a common pairing for containerised web applications. See Cloud Run Overview for how that deployment model works.

When Cloud SQL for MySQL may not be the right fit

Not every workload belongs on a relational database. Before choosing Cloud SQL, consider whether the data shape and access patterns are actually a good match. The Choosing the Right GCP Storage Service guide walks through the full decision flow across all GCP storage options.

  • Document-shaped or schema-flexible data. If your data does not fit into fixed rows and columns, or if different records in a collection have different shapes, Firestore may be a better choice. It is serverless, scales automatically, and handles real-time sync for mobile and web clients without you provisioning instance sizes.

  • Analytical or reporting workloads over large datasets. Cloud SQL is an OLTP database built for transactional reads and writes. Running large analytical queries over hundreds of millions of rows will be slow and expensive compared to BigQuery, which is built for exactly that kind of workload.

  • Globally distributed writes with strong consistency. Cloud SQL is a regional service. If you need a globally distributed relational database with strong consistency across multiple continents, Cloud Spanner is designed for that. Cloud SQL cannot synchronously replicate across regions.

  • Workloads requiring deep OS-level MySQL control. If your workload requires custom MySQL plugins, specific kernel-level tuning, or MySQL features that Cloud SQL restricts, you can run MySQL yourself on Compute Engine. You lose the managed service benefits but gain full control over the stack.

Creating a MySQL instance

Use gcloud sql instances create to provision an instance. The command below sets a reasonable production baseline: SSD storage, automatic storage growth, automated daily backups, and binary logging for point-in-time recovery.

gcloud sql instances create my-mysql-instance \
  --database-version=MYSQL_8_0 \
  --tier=db-n1-standard-2 \
  --region=europe-west2 \
  --storage-type=SSD \
  --storage-size=20GB \
  --storage-auto-increase \
  --backup-start-time=03:00 \
  --enable-bin-log

A few decisions worth understanding before you run this:

  • Version. Use MySQL 8.0 for new instances. It is the current active major version and receives ongoing maintenance. Earlier major versions are available but approaching end-of-life. Check the Cloud SQL documentation for the current supported MySQL version list before choosing, as minor versions are updated over time.

  • Machine type. The —tier flag controls CPU and RAM. Use db-f1-micro for development and non-critical staging. For production, choose a tier based on your expected connection count and query throughput. Undersized instances are one of the most common causes of production slowdowns.

  • Region. Pick the region closest to your application. Cloud SQL is a regional service, so cross-region latency adds up on every query. Think about this alongside where your application is deployed.

Enable binary logging at creation time

Binary logging must be enabled when the instance is created using —enable-bin-log. Enabling it after the fact requires a restart and leaves a gap in your recovery window. Without binary logging, point-in-time recovery is unavailable and your recovery point is limited to the most recent daily backup. Do not skip this flag for any production instance.

Storage auto-increase

Storage auto-increase only ever grows storage, never shrinks it. If usage drops, your provisioned size stays at the peak. Enable it for any write-heavy instance unless you have a strict cost ceiling and actively manage storage usage.

Managing users and databases

Cloud SQL creates a default root user on every instance. Secure it immediately, then create a dedicated application user. Root should be reserved for administrative tasks only.

# Set the root password
gcloud sql users set-password root \
  --instance=my-mysql-instance \
  --host=% \
  --password=your-secure-password

# Create a dedicated application user
gcloud sql users create app-user \
  --instance=my-mysql-instance \
  --host=% \
  --password=app-user-password

# Create a database
gcloud sql databases create my-app-db \
  --instance=my-mysql-instance

# List databases on the instance
gcloud sql databases list --instance=my-mysql-instance
Never use root for application connections

Root has full administrative access to every database on the instance. A compromised application connection means an attacker has complete control over all your data. Create a dedicated application user and grant it only SELECT, INSERT, UPDATE, and DELETE on the specific database it needs. Nothing more.

Granting only the permissions the application requires follows the principle of least privilege and limits what an attacker can do with a compromised connection. The application user does not need CREATE TABLE, DROP, or access to other databases on the same instance.

Store passwords in Secret Manager

Database passwords embedded in environment variables, container images, or source code end up in version control, build logs, and container registries. Use Secret Manager to store credentials and retrieve them at runtime. This applies especially to Cloud Run and GKE deployments where images are pushed to a registry.

Host restriction

The —host=% flag allows the user to connect from any host. For applications that always connect from a known IP range, restricting this adds a secondary layer of access control. In practice, private IP or the Auth Proxy handle the primary network boundary, so host restriction is optional but harmless.

Connecting to your instance

How you connect depends on where your application runs and what security model you need. There are three main patterns, and choosing correctly matters more for databases than for most services.

  • Cloud SQL Auth Proxy. Authenticates using your IAM identity or a service account, establishes an encrypted tunnel to the instance, and listens on a local port. Your application connects to 127.0.0.1:3306 as if connecting to a local database. The proxy handles all authentication and encryption. This is the standard approach for local development and for workloads on Compute Engine or Cloud Run where private IP is not in use.

  • Private IP. Places your Cloud SQL instance on your VPC, reachable from other resources in the same network without going over the public internet. Preferred for production workloads on GKE, Compute Engine, or Cloud Run with VPC access configured. See VPC Networks Explained for how VPC connectivity works in GCP.

  • Public IP with authorised networks. Exposes the database on a public IP, restricted to a specific list of IP ranges. Acceptable for developer laptops in controlled settings. Not suitable for production workloads. See Private vs Public IP Addresses for a fuller explanation of the tradeoffs between these models.

Do not open 0.0.0.0/0 as an authorised network

Setting 0.0.0.0/0 as an authorised network exposes your MySQL port to the entire internet. Use private IP or the Auth Proxy for production. If you must use public IP for development access, restrict the CIDR to your specific IP address or your office network range.

# Run the Cloud SQL Auth Proxy
./cloud-sql-proxy my-project:europe-west2:my-mysql-instance

# In a second terminal, connect with the mysql client
mysql -u app-user -p --host=127.0.0.1 --port=3306 my-app-db

For a thorough walkthrough of each connection method, including Kubernetes sidecar setup and IAM database authentication, see Connecting to Cloud SQL Securely.

Configuring MySQL with database flags

On a self-managed MySQL instance, you would edit my.cnf to tune server settings. Cloud SQL does not give you OS access, so database flags are the only mechanism for changing server configuration. The flag system maps Cloud SQL flag names to the underlying MySQL system variables.

Analogy

Database flags are like submitting a maintenance request to your building manager. You can ask for the thermostat to be adjusted, but you cannot go into the utility room and do it yourself. The building manager decides which requests are supported. Not everything on your list will be available.

# Enable slow query logging with a 1-second threshold
gcloud sql instances patch my-mysql-instance \
  --database-flags=slow_query_log=on,long_query_time=1

# Check the current flags on an instance
gcloud sql instances describe my-mysql-instance \
  --format="value(settings.databaseFlags)"

Some flags require a restart to take effect. The gcloud output will indicate when this is the case. Schedule restarts during a maintenance window for production instances. Not every MySQL system variable has a corresponding Cloud SQL flag, so check the supported flags list in the Cloud SQL documentation before building anything that depends on a specific flag being available.

SUPER at runtime

Operations requiring SUPER privilege at runtime, such as changing certain global variables via SQL, must use the flags mechanism. You cannot use SET GLOBAL for variables that Cloud SQL has mapped to flags.

Read replicas, backups, and availability

Cloud SQL offers several overlapping features that address different concerns. Understanding what each one does independently prevents a common class of production mistakes.

Automated backups are daily snapshots of your instance stored in Cloud Storage. They allow restoration to the state at any backup point. Backups alone do not give you second-level recovery granularity.

Point-in-time recovery (PITR) combines daily backups with continuous binary logs to let you restore to any second within the retention window. Binary logging must be explicitly enabled with —enable-bin-log. Without it, PITR is unavailable and your recovery point is the most recent daily backup.

Read replicas are separate Cloud SQL instances that continuously replicate from the primary. Send read-heavy traffic to a replica to reduce load on the primary. Replicas do not provide automatic failover.

High availability provisions a synchronous standby in a different zone within the same region. If the primary zone has a failure, Cloud SQL automatically promotes the standby and updates the connection endpoint. This is automatic failover. Read replicas are not.

Read replicas are not a failover mechanism

If the primary instance fails, a read replica keeps running but cannot accept writes and will not promote itself. Promoting a replica to standalone requires manual action during an outage, which is exactly when you least want that dependency. If you need automatic failover, enable high availability at instance creation or patch the instance to enable it.

For configuration details, retention window settings, and a worked example of PITR setup, see Cloud SQL Backups, PITR, and High Availability.

# Create a read replica in the same region
gcloud sql instances create my-mysql-replica \
  --master-instance-name=my-mysql-instance \
  --region=europe-west2 \
  --tier=db-n1-standard-2

# Promote a replica to a standalone instance (breaks replication permanently)
gcloud sql instances promote-replica my-mysql-replica
Promotion is permanent

Once a replica is promoted, it becomes an independent primary and replication from the original is severed. Use promotion for major version upgrades, emergency recovery, or planned migrations — not as part of routine operations.

Cloud SQL for MySQL vs self-managed MySQL

Choosing between Cloud SQL and running MySQL yourself on Compute Engine is a question of operational simplicity versus control. Cloud SQL is the right default for the vast majority of application databases. Self-managed MySQL makes sense only when a specific technical requirement cannot be satisfied by the managed service.

What Cloud SQL handles for you: OS and database patching, automated daily backups, PITR setup, high availability failover, storage management, and minor version upgrades within a major version. You do not need to schedule, test, or think about any of these in most cases.

What you give up: full my.cnf control, the SUPER privilege for runtime SQL, custom MySQL plugins, and any configuration outside the supported database flags list.

Where self-managed MySQL wins: when you genuinely need a custom plugin, specific kernel-level tuning, or a MySQL feature that Cloud SQL restricts. If you make that choice, be clear-eyed about the operational cost. You own patching, backup testing, and failover configuration. None of it is free.

Cost: Cloud SQL instances are priced per hour plus storage. Self-managed MySQL on Compute Engine may cost less for very large instances if you have strong database operations capability in-house. For most teams, the managed service is the more economical choice once you account for operational effort.

If you are evaluating PostgreSQL alongside MySQL, see PostgreSQL on Cloud SQL for the key differences in how each engine behaves on the managed service.

Common mistakes

  1. Using root for application connections. Root has full administrative access to every database on the instance. A compromised application gives an attacker complete control. Create a dedicated user with only SELECT, INSERT, UPDATE, and DELETE on the specific database the application needs.

  2. Forgetting to enable binary logging before going to production. Binary logging is off by default and must be enabled at instance creation. Enabling it later requires a restart and leaves a gap in your recovery window. Without binary logging, PITR is unavailable and your recovery point is the last daily backup.

  3. Treating read replicas as automatic failover. Replicas do not promote themselves if the primary fails. For automatic failover you need a high-availability instance. A read replica must be manually promoted during an outage, which requires human intervention at exactly the wrong moment.

  4. Using public IP with an overly broad authorised network range. Setting 0.0.0.0/0 as an authorised network exposes your database to the entire internet. Use private IP or the Auth Proxy for production. If you must use public IP for development access, restrict the range to specific known CIDRs.

  5. Hardcoding database credentials in application code or images. Credentials embedded in source code end up in version control, build logs, and container registries. Use Secret Manager to store passwords and retrieve them at runtime.

  6. Undersizing instances for production workloads. Cloud SQL allows live resizing without data loss, but a resize still requires a brief restart. An undersized instance under load will cause slow queries and connection timeouts before you get a chance to resize. Choose a tier based on your expected concurrent connections and working set size, not just raw query throughput.

Frequently asked questions

Is Cloud SQL the same as MySQL?

Cloud SQL for MySQL uses a genuine MySQL engine, so your SQL, schemas, and drivers work as expected. The difference is operational: Google manages the underlying VM, OS patching, backups, failover, and storage growth. You manage your schemas, users, data, and configuration. One notable restriction is the SUPER privilege. Certain operations that require SUPER must go through the Cloud SQL database flags mechanism instead of being run as SQL statements.

Can I migrate an existing MySQL database to Cloud SQL?

Yes. For smaller databases, export with mysqldump and import using gcloud sql import sql or the Cloud Console. For larger migrations or situations where you need minimal downtime, use Database Migration Service (DMS), which supports continuous replication from an external MySQL source so you can cut over with only seconds of downtime. Check the Cloud SQL MySQL compatibility documentation before migrating workloads that depend on features restricted by the managed service, such as specific SUPER-level operations.

Should I use public IP or private IP to connect to Cloud SQL?

Private IP is preferred for production. It keeps your database unreachable from the public internet and routes traffic within your VPC. The Cloud SQL Auth Proxy is a good option when your workload is outside your VPC, for local development, or when you want IAM-authenticated connections without managing TLS certificates yourself. Public IP with an authorised networks allowlist is acceptable for developer laptops during development only.

Do read replicas provide failover if the primary fails?

No. Read replicas replicate continuously from the primary and are useful for offloading read queries, but they do not automatically become the primary if it fails. Automatic failover requires a Cloud SQL high-availability instance, which provisions a synchronous standby in a different zone. A read replica can be manually promoted to standalone, but that requires human intervention during an outage.

When should I use Firestore instead of Cloud SQL for MySQL?

Firestore is a better fit when your data is document-shaped rather than tabular, you need real-time sync for mobile or web clients, or you want a serverless database that scales without provisioning instance sizes. Cloud SQL for MySQL is the right choice when you need relational data with foreign keys, multi-table transactions, complex SQL queries, or when migrating an existing MySQL-based application to GCP.

Last verified: 23 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.