When I built my first Android app with a real backend, I made a classic mistake. I rented a small virtual machine, installed MySQL on it myself, and felt very proud. Three months later the disk filled up at 2 AM, the database stopped, and I lost a few hours of orders because my “backup script” had quietly failed weeks earlier. That night I moved everything to Google Cloud SQL, and I have not touched a database server since.
In this tutorial I will explain Google Cloud SQL in simple words: what it is, what it is used for, when you should use it (and when you should not), and exactly how to use it, with a real-time example of a grocery delivery app that you can follow step by step.

Table of Contents
Table of Contents
What Is Google Cloud SQL?
Google Cloud SQL is a fully managed relational database service on Google Cloud Platform (GCP). It runs three popular database engines for you:
- MySQL
- PostgreSQL
- SQL Server
“Fully managed” is the important part. You still write normal SQL – CREATE TABLE, INSERT, SELECT, joins, indexes – but Google takes care of the boring and risky work: installing the database, patching it, taking backups, replacing failed hardware, and switching to a standby copy if a zone goes down.
If you are new to databases, read our guides on what a database is and RDBMS first. Google Cloud SQL is simply an RDBMS that lives in Google’s data centre instead of your laptop or office server.
Simple definition: Google Cloud SQL is MySQL, PostgreSQL or SQL Server running on Google Cloud, where Google manages the server, backups, updates and high availability, and you only manage your data and queries.
A simple real-life comparison
Running your own database server is like owning a car: you buy it, service it, fix it and worry about it. Google Cloud SQL is like a reliable cab service. You still decide where to go (your data and queries), but someone else maintains the vehicle, refuels it and sends a new one if it breaks down.
Key features of Google Cloud SQL
| Feature | What it means for you |
|---|---|
| Automated backups | Daily backups plus point-in-time recovery, so you can restore to a specific minute. |
| High availability (HA) | A standby copy in another zone takes over automatically if the main one fails. |
| Read replicas | Extra read-only copies to handle heavy reporting or read traffic. |
| Automatic storage increase | Disk grows by itself before it gets full (no more 2 AM surprises). |
| Security | Encryption at rest and in transit, private IP, IAM database login. |
| Easy integration | Works smoothly with Cloud Run, Cloud Functions, GKE, App Engine and BigQuery. |
How Google Cloud SQL Works
When you create a Google Cloud SQL “instance”, Google starts a virtual machine with your chosen database engine, attaches a persistent disk, and gives you a connection name such as my-project:asia-south1:grocery-db. Here is what happens behind the scenes:
- Instance – a managed server running MySQL, PostgreSQL or SQL Server. You pick the CPU, memory and region.
- Storage – SSD or HDD disk that can grow automatically, up to 64 TB.
- Databases and users – inside one instance you can create many databases and users, like any normal server.
- Connections – your app connects through a public IP, a private IP inside your VPC, or the secure Cloud SQL Auth Proxy / connectors.
- Backups and logs – Google takes backups and keeps transaction logs, so you can restore to an earlier point.
- High availability – if you turn on HA, a standby instance in a second zone is kept in sync and takes over within about a minute if needed.
Enterprise vs Enterprise Plus edition
| Feature | Enterprise | Enterprise Plus |
|---|---|---|
| Best for | Most apps, startups, internal tools | Business-critical, high-traffic systems |
| Availability SLA (with HA) | 99.95% | 99.99% |
| Performance | Standard | Faster machines and data cache |
| Maintenance downtime | Short | Near-zero |
| Cost | Lower | Higher |
For learning and most small to medium projects, the Enterprise edition is more than enough.
7 Uses of Google Cloud SQL
Google Cloud SQL is used wherever an application needs structured data with relationships and transactions. These are the seven uses I see most in real projects:
- Backend database for web and mobile apps – users, products, orders, payments for e-commerce, food delivery or booking apps.
- Business applications – CRM, ERP, HR, billing and inventory systems that need reliable transactions.
- Migrating on-premises databases – move an existing MySQL, PostgreSQL or SQL Server database to the cloud with Database Migration Service.
- Content management systems – WordPress, Drupal and similar sites run on MySQL.
- SaaS products – multi-customer applications where each customer’s data must stay consistent.
- Operational data for analytics – BigQuery can read Google Cloud SQL tables directly with federated queries.
- Geospatial and AI apps – PostgreSQL extensions like PostGIS (maps) and pgvector (AI embeddings) work in Cloud SQL.
When to Use Google Cloud SQL (and When Not To)
✅ Use Google Cloud SQL when:
- Your data has a clear structure with tables and relationships (customers → orders → order items).
- You need ACID transactions – for example, money must leave one account and enter another, or nothing should happen at all.
- Your team already knows SQL, MySQL or PostgreSQL and you don’t want to learn a new database.
- You want backups, patching and failover handled for you.
- Your database size is from a few MB up to a few TB, and traffic comes from one main region.
❌ Choose something else when:
- You need global scale with users writing from many continents → use Cloud Spanner.
- You are running analytics on billions of rows → use BigQuery.
- Your data is flexible JSON documents with real-time sync to mobile apps → use Firestore.
- You need very high-speed writes of time-series or IoT data → use Bigtable.
- You need full control over the database server or OS → run it yourself on Compute Engine.
Google Cloud SQL vs Spanner vs Firestore vs BigQuery
| Service | Type | Best for | Scale |
|---|---|---|---|
| Cloud SQL | Relational (MySQL/PostgreSQL/SQL Server) | App backends, transactions | Up to a few TB, one region |
| Spanner | Relational, distributed | Global banking, gaming | Unlimited, multi-region |
| Firestore | NoSQL documents | Mobile apps, real-time sync | Large, automatic |
| BigQuery | Data warehouse | Analytics and reports | Petabytes |
How to Use Google Cloud SQL: Real-Time Example
Business scenario: A local grocery shop in Pune wants an Android app for home delivery. Customers place orders in the app, the shop owner sees them on a dashboard, and every night the owner wants a sales report. We will use:
- Google Cloud SQL (PostgreSQL) to store customers, products and orders.
- Cloud Run to host a small Python API that the Android app calls.
- BigQuery to read sales data for reports without slowing down the app.
Android App ──► Cloud Run API (Python) ──► Google Cloud SQL (PostgreSQL) ──► BigQuery reports (place order) (grocery-api) (grocery-db) (EXTERNAL_QUERY)
Step 1: Enable the API and create a Cloud SQL instance
gcloud services enable sqladmin.googleapis.com
gcloud sql instances create grocery-db \
--database-version=POSTGRES_16 \
--edition=ENTERPRISE \
--tier=db-g1-small \
--region=asia-south1 \
--storage-auto-increase \
--backup-start-time=02:00 \
--root-password=ChangeThisStrongPassword
This takes a few minutes. db-g1-small is a low-cost shared machine, good for testing. For production, choose a dedicated tier such as db-custom-2-7680 (2 vCPU, 7.5 GB RAM).
Prefer the console? Go to Google Cloud Console → SQL → Create instance → PostgreSQL, enter an instance ID and password, choose the region asia-south1 (Mumbai), and click Create.
Step 2: Create a database and an app user
gcloud sql databases create grocery --instance=grocery-db
gcloud sql users create appuser \
--instance=grocery-db \
--password=AnotherStrongPassword
Never let your app log in as the postgres admin user. A separate user with limited rights is much safer.
Step 3: Connect and create the tables
The quickest way is gcloud sql connect, which opens a psql session (or use Cloud SQL Studio in the console to run SQL in the browser):
gcloud sql connect grocery-db --user=postgres --database=grocery
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
phone VARCHAR(15) UNIQUE NOT NULL,
address TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price NUMERIC(10,2) NOT NULL,
stock INT DEFAULT 0
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id),
product_id INT REFERENCES products(product_id),
quantity INT NOT NULL,
total NUMERIC(10,2) NOT NULL,
status VARCHAR(20) DEFAULT 'PLACED',
order_date TIMESTAMP DEFAULT NOW()
);
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO appuser;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO appuser;
INSERT INTO products (name, price, stock) VALUES
('Aashirvaad Atta 5kg', 285.00, 50),
('Amul Butter 500g', 275.00, 40),
('Tata Salt 1kg', 28.00, 100);
Notice how the tables are linked with REFERENCES. This is exactly why we picked a relational database – see our post on normalization in SQL to understand why we split data like this.
Step 4: Write the API that talks to Google Cloud SQL
main.py – a small Flask API. On Cloud Run, Google Cloud SQL is reachable through a Unix socket at /cloudsql/CONNECTION_NAME, so no public IP is needed.
import os
import psycopg2
from flask import Flask, request, jsonify
app = Flask(__name__)
def get_conn():
return psycopg2.connect(
host=f"/cloudsql/{os.environ['INSTANCE_CONNECTION_NAME']}",
dbname=os.environ["DB_NAME"],
user=os.environ["DB_USER"],
password=os.environ["DB_PASS"],
)
@app.post("/orders")
def place_order():
data = request.get_json()
conn = get_conn()
try:
with conn: # one transaction
with conn.cursor() as cur:
cur.execute("SELECT price, stock FROM products WHERE product_id = %s FOR UPDATE",
(data["product_id"],))
price, stock = cur.fetchone()
if stock < data["quantity"]:
return jsonify({"error": "Out of stock"}), 400
total = price * data["quantity"]
cur.execute("UPDATE products SET stock = stock - %s WHERE product_id = %s",
(data["quantity"], data["product_id"]))
cur.execute("""INSERT INTO orders (customer_id, product_id, quantity, total)
VALUES (%s, %s, %s, %s) RETURNING order_id""",
(data["customer_id"], data["product_id"], data["quantity"], total))
order_id = cur.fetchone()[0]
return jsonify({"order_id": order_id, "total": float(total)}), 201
finally:
conn.close()
@app.get("/orders/today")
def todays_orders():
conn = get_conn()
with conn.cursor() as cur:
cur.execute("""SELECT o.order_id, c.name, p.name, o.quantity, o.total
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
JOIN products p ON p.product_id = o.product_id
WHERE o.order_date::date = CURRENT_DATE""")
rows = cur.fetchall()
conn.close()
return jsonify(rows)
Look at the place_order function. Reducing stock and inserting the order happen in one transaction. If anything fails in the middle, both changes are rolled back. Two customers can’t buy the last packet of butter at the same time, thanks to FOR UPDATE. This is the real power of Google Cloud SQL for business apps.
requirements.txt
flask
gunicorn
psycopg2-binary
Step 5: Deploy to Cloud Run and connect it to Cloud SQL
gcloud run deploy grocery-api \
--source=. \
--region=asia-south1 \
--add-cloudsql-instances=my-project:asia-south1:grocery-db \
--set-env-vars=INSTANCE_CONNECTION_NAME=my-project:asia-south1:grocery-db,DB_NAME=grocery,DB_USER=appuser \
--set-secrets=DB_PASS=grocery-db-pass:latest \
--allow-unauthenticated
The password is stored in Secret Manager (secret name grocery-db-pass), not in the code. The Cloud Run service account also needs the Cloud SQL Client role. Our IAM and Service Account guides show how to grant it.
Step 6: Test the API
curl -X POST https://grocery-api-xxxxx-el.a.run.app/orders \
-H "Content-Type: application/json" \
-d '{"customer_id": 1, "product_id": 2, "quantity": 3}'
# Response
{"order_id": 1, "total": 825.0}
The Android app calls this same URL with Retrofit or OkHttp. The shop owner’s dashboard calls /orders/today to see today’s orders.
Step 7: Turn on high availability before going live
gcloud sql instances patch grocery-db --availability-type=REGIONAL
# Create an on-demand backup before any big change
gcloud sql backups create --instance=grocery-db
Now if one zone in Mumbai has a problem, Google Cloud SQL switches to the standby automatically. Customers keep ordering and you keep sleeping.
Step 8: Nightly sales report in BigQuery
Running heavy reports on the live database can slow down the app. Instead, create a BigQuery connection to the Cloud SQL instance and query it with EXTERNAL_QUERY:
SELECT *
FROM EXTERNAL_QUERY(
"my-project.asia-south1.grocery-conn",
"""SELECT p.name AS product, SUM(o.quantity) AS units, SUM(o.total) AS revenue
FROM orders o JOIN products p ON p.product_id = o.product_id
WHERE o.order_date::date = CURRENT_DATE
GROUP BY p.name""");
You can schedule this query in BigQuery every night at 11 PM and save the result in a table for dashboards. For bigger loads, add a read replica and point reports at it instead of the main instance.
Google Cloud SQL Pricing
Google Cloud SQL is charged mainly for:
- CPU and memory – per hour while the instance is running.
- Storage – per GB per month for data and backups.
- Networking – data sent out of Google Cloud.
- Licence – only for SQL Server editions.
Unlike Cloud Functions, there is no always-free tier, because the instance runs all the time. New Google Cloud accounts get free trial credits that are perfect for learning. A small shared-core PostgreSQL instance for testing costs only a little per month, while high availability roughly doubles the instance cost because a standby runs too. Always check the latest numbers on the official Cloud SQL pricing page.
Money-saving tip: stop test instances when you’re not using them with gcloud sql instances patch grocery-db --activation-policy=NEVER, and start them again with --activation-policy=ALWAYS. You still pay for storage, but not for CPU.
Advantages and Disadvantages
| Advantages | Disadvantages |
|---|---|
| No database server to install or patch | No always-free tier; instance cost runs 24×7 |
| Automatic backups and point-in-time recovery | No root/OS access to the server |
| High availability with automatic failover | Scales vertically; not built for global writes |
| Standard MySQL, PostgreSQL and SQL Server – no new language | Some extensions and settings are restricted |
| Easy connection to Cloud Run, Functions and BigQuery | Short downtime during some maintenance (Enterprise edition) |
Best Practices and Common Mistakes
Best practices for Google Cloud SQL
- Use private IP or the Cloud SQL Auth Proxy/connectors instead of opening a public IP to the world.
- Turn on high availability for production and test a failover once.
- Keep automated backups and point-in-time recovery enabled.
- Store passwords in Secret Manager, or use IAM database authentication.
- Use connection pooling (or limit Cloud Run max instances) so you don’t exceed the database’s connection limit.
- Add indexes on columns used in WHERE and JOIN, and watch slow queries in Query Insights.
- Choose the same region for Cloud SQL and your app to reduce latency.
Common mistakes I have seen
- Allowing 0.0.0.0/0 in authorised networks “just for testing” and forgetting to remove it.
- Connecting the app as the admin user instead of a limited app user.
- Leaving big test instances running for weeks and getting a surprise bill.
- Running heavy reports on the primary during business hours instead of a replica or BigQuery.
- Opening a new connection for every request without closing it, until the database refuses new connections.
Interview Questions on Google Cloud SQL
- What is Cloud SQL? A fully managed relational database service for MySQL, PostgreSQL and SQL Server on Google Cloud.
- How is high availability achieved? With a regional instance: a standby in another zone is synchronously replicated and takes over automatically.
- Read replica vs HA standby? A read replica serves read traffic; the HA standby does not serve traffic and only exists for failover.
- How does Cloud Run connect to Cloud SQL? Using
--add-cloudsql-instances(Unix socket) or the Cloud SQL language connectors, with the Cloud SQL Client role. - Cloud SQL vs Spanner? Cloud SQL is for regional workloads up to a few TB; Spanner is for globally distributed, horizontally scalable workloads.
- How do you query Cloud SQL from BigQuery? Create a connection and use
EXTERNAL_QUERY(federated query).
Frequently Asked Questions
Is Google Cloud SQL free?
No, there is no permanent free tier. New accounts can use free trial credits, and small test instances are cheap if you stop them when not in use.
Should I choose MySQL or PostgreSQL in Google Cloud SQL?
Both are excellent. Choose MySQL if your app or CMS already uses it (like WordPress). Choose PostgreSQL for new projects that need advanced features such as JSON queries, PostGIS or pgvector.
Can I connect my Android app directly to Google Cloud SQL?
You can, but you shouldn’t. Putting database passwords inside an app is a big security risk. Always put an API (Cloud Run or Cloud Functions) between the app and the database, like in our example.
How big can a Cloud SQL database be?
Storage can grow up to 64 TB per instance, which is more than enough for most business applications.
How do I move my existing database to Google Cloud SQL?
For small databases, export a SQL dump and import it from Cloud Storage. For larger or live databases, use Google’s Database Migration Service, which copies data continuously with minimal downtime.
Conclusion
Google Cloud SQL gives you the databases you already know – MySQL, PostgreSQL and SQL Server – without the stress of running a server. Use it as the backend for web and mobile apps, business systems and SaaS products whenever your data is structured and needs reliable transactions. Pair it with Cloud Run for your API, Cloud Functions for background jobs, and BigQuery for reports, and you have a complete, production-ready setup.
My advice: create a small test instance today, run the grocery example from this post, and then stop the instance when you’re done. Once you see an order go from an API call into a real cloud database in seconds, the whole picture will click. For more details, the official Google Cloud SQL documentation is the best next step.