DevOpsIndex

GCP Databases

Managed relational, NoSQL, globally distributed, and caching databases.


Database Service Map

Use case AWS GCP
Managed Postgres RDS Postgres / Aurora Cloud SQL / AlloyDB
Managed MySQL RDS MySQL / Aurora MySQL Cloud SQL MySQL
Global ACID SQL Aurora Global (lag) Cloud Spanner (TrueTime, no lag)
NoSQL document DynamoDB / DocumentDB Firestore
Wide-column / time-series DynamoDB single-table Bigtable
In-memory cache ElastiCache (Redis/Memcached) Memorystore
Analytical / data warehouse Redshift BigQuery (see bigquery.md)

Cloud SQL — Managed MySQL, PostgreSQL, SQL Server

Cloud SQL is the closest thing to RDS. Supports Postgres, MySQL, and SQL Server with automated backups, HA, and read replicas.

Create an Instance

# PostgreSQL instance
gcloud sql instances create my-postgres \
  --database-version=POSTGRES_15 \
  --region=us-central1 \
  --tier=db-n1-standard-4 \         # 4 vCPU, 15 GB RAM
  --storage-size=100GB \
  --storage-type=SSD \
  --storage-auto-increase \          # like Aurora auto-grow
  --backup-start-time=04:00 \
  --availability-type=REGIONAL       # HA (standby in another zone)

# Create a database and user
gcloud sql databases create myapp --instance=my-postgres
gcloud sql users create myuser --instance=my-postgres --password=secret

Connection Methods

Method 1: Cloud SQL Auth Proxy (recommended)
  Runs as a sidecar, handles TLS + IAM auth automatically
  AWS analog: RDS Proxy

Method 2: Private IP (VPC-native)
  SQL instance gets a private IP in your VPC
  Direct connection from GCE/GKE

Method 3: Public IP + SSL + authorized networks
  Avoid in production
# Cloud SQL Auth Proxy (local dev)
./cloud-sql-proxy my-project:us-central1:my-postgres &
# connects on localhost:5432

# Private IP (best for production)
gcloud sql instances patch my-postgres \
  --network=my-vpc \
  --no-assign-ip              # disable public IP

HA and Read Replicas

# HA is set with --availability-type=REGIONAL at creation
# This creates a standby in a different zone (like RDS Multi-AZ)

# Add a read replica
gcloud sql instances create my-postgres-replica \
  --master-instance-name=my-postgres \
  --region=us-east1          # cross-region read replica

# Promote replica to primary (for migration/disaster recovery)
gcloud sql instances promote-replica my-postgres-replica

Cloud SQL vs RDS Comparison

Cloud SQL AWS RDS
Postgres max version 15 16
Storage auto-grow Yes Yes
Multi-AZ HA Regional (different zone standby) Multi-AZ (synchronous standby)
Read replicas Yes, cross-region Yes, cross-region
Managed proxy Cloud SQL Auth Proxy RDS Proxy
IAM auth Yes (passwordless) Yes (IAM DB auth)
Point-in-time recovery Yes (7-day window) Yes (35-day max)
Max storage 64 TB 64 TB
Maintenance window Configurable Configurable

AlloyDB — PostgreSQL on Steroids

AlloyDB is GCP's proprietary high-performance Postgres. It's Google's answer to Amazon Aurora — built on Postgres protocol but with a custom storage layer.

RDS Postgres              Aurora Postgres            AlloyDB
──────────────────────────────────────────────────────────────
Standard Postgres         Custom storage engine      Custom storage engine
~3x slower than Aurora    4x faster than RDS PG      2x faster than Aurora
Community Postgres limits Up to 128 TB               Up to 64 TB (growing)
No columnar              No columnar                 Built-in columnar for analytics

When to use AlloyDB over Cloud SQL:

  • OLTP workloads needing 4-5× more throughput than Cloud SQL
  • Hybrid OLTP + analytics (AlloyDB has a columnar engine for fast analytics on live data)
  • Require sub-second failover (AlloyDB uses distributed storage, no failover replica sync)
gcloud alloydb clusters create my-cluster \
  --region=us-central1 \
  --password=admin-pass

gcloud alloydb instances create my-primary \
  --instance-type=PRIMARY \
  --cluster=my-cluster \
  --region=us-central1 \
  --cpu-count=4

Cloud Spanner — Globally Distributed ACID SQL

Spanner is the only database in the world that provides both horizontal scaling AND global strong consistency. Aurora Global has seconds of replication lag. Spanner has ~10ms at global scale.

How TrueTime Works

sequenceDiagram
    participant TX1 as Transaction (us-central1)
    participant TS as TrueTime (atomic clocks + GPS)
    participant TX2 as Transaction (europe-west1)

    TX1->>TS: Request commit timestamp
    TS-->>TX1: T1 = [Tearliest, Tlatest] (nanosecond uncertainty)
    Note over TX1: Wait for uncertainty to pass
    TX1->>TX1: Commit at Tlatest
    TX2->>TS: Read timestamp
    TS-->>TX2: T2 > T1 (guaranteed)
    Note over TX2: Reads see TX1's committed data

Google uses GPS receivers and atomic clocks in every datacenter. Every commit waits out the clock uncertainty (typically 4-7ms). This guarantees linearizability globally — reads always see the latest committed state, across continents.

When to Use Spanner

Use Spanner when:
  - Financial transactions across regions (banking, payments)
  - Inventory systems that must be globally consistent
  - Gaming (leaderboards, inventory) at global scale
  - Cannot tolerate any read staleness, even milliseconds

Don't use Spanner when:
  - Your workload is single-region (Cloud SQL is cheaper)
  - You need complex joins over large datasets (BigQuery is better)
  - Budget-constrained ($0.65/node-hour minimum)
# Create a Spanner instance
gcloud spanner instances create my-spanner \
  --config=regional-us-central1 \      # or nam4, eur3, global1
  --description="Production" \
  --nodes=3                            # 2,000 QPS per node

# Multi-region config (global consistency)
gcloud spanner instances create global-spanner \
  --config=nam-eur-asia1 \             # 3 continents
  --nodes=3

# Create database and schema
gcloud spanner databases create mydb --instance=my-spanner
gcloud spanner databases ddl update mydb --instance=my-spanner \
  --ddl='CREATE TABLE orders (
    order_id STRING(36) NOT NULL,
    user_id STRING(36) NOT NULL,
    amount NUMERIC NOT NULL,
    created_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
  ) PRIMARY KEY (order_id)'

Spanner vs Aurora Global

Cloud Spanner Aurora Global
Replication lag ~0ms (TrueTime, strong consistency) 1-2 seconds (async replication)
Global write Any region (multi-master) One primary region only
SQL compatibility GoogleSQL dialect (ANSI SQL + extensions) Standard MySQL / Postgres
Schema changes Online, no downtime Downtime for some ALTER TABLE
Cost $0.65/node-hour ~$0.29/hour for r5.large
Auto-scaling Yes (serverless Spanner) No (fixed instance sizes)

Firestore — Serverless Document Database

Firestore = GCP's MongoDB / DynamoDB hybrid. Serverless (scales to zero), document model, real-time listeners.

DynamoDB                  Firestore
──────────────────────────────────────────────────
Tables                    Collections
Items                     Documents
Partition + sort key      Document ID (path-based)
GSI                       Composite indexes
Streams                   Real-time listeners
$0.25/GB + $0.25/RCU      $0.06/GB + $0.06/100K reads

Firestore Data Model

/users/                    ← Collection
  user-123/                ← Document
    name: "Alice"
    email: "alice@example.com"
    orders/                ← Sub-collection
      order-abc/
        amount: 99.99
        status: "shipped"
from google.cloud import firestore

db = firestore.Client()

# Write
db.collection("users").document("user-123").set({
    "name": "Alice",
    "email": "alice@example.com",
    "created_at": firestore.SERVER_TIMESTAMP
})

# Read
doc = db.collection("users").document("user-123").get()
print(doc.to_dict())

# Query (must create composite index for multi-field queries)
users = db.collection("users")\
    .where("status", "==", "active")\
    .where("plan", "==", "premium")\
    .order_by("created_at", direction=firestore.Query.DESCENDING)\
    .limit(10)\
    .stream()

# Real-time listener (no equivalent in DynamoDB)
def on_snapshot(docs, changes, read_time):
    for change in changes:
        print(f"Change: {change.type.name} {change.document.id}")

db.collection("orders").on_snapshot(on_snapshot)

Firestore Modes

Mode Best for
Native Mobile/web apps, real-time, flexible schema
Datastore Legacy mode, no real-time, lower cost for batch

Use Native mode for all new projects.


Memorystore — Managed Redis and Memcached

Memorystore = GCP's ElastiCache.

# Create Redis instance
gcloud redis instances create my-redis \
  --size=5 \                    # 5 GB
  --region=us-central1 \
  --redis-version=redis_7_0 \
  --tier=STANDARD               # STANDARD = HA with replica; BASIC = no HA

# Get connection info
gcloud redis instances describe my-redis --region=us-central1
# → host: 10.0.0.50, port: 6379

# Connect from GKE pod (same VPC)
redis-cli -h 10.0.0.50 -p 6379

Memorystore vs ElastiCache

Memorystore ElastiCache
Redis versions 6.x, 7.x 5.x, 6.x, 7.x
Cluster mode Memorystore for Redis Cluster Cluster Mode Enabled
HA Standard tier (primary + replica) Multi-AZ with auto-failover
Encryption In-transit + at-rest In-transit + at-rest
Auth AUTH string AUTH token
Persistence RDB snapshots RDB + AOF
Cost (5GB) ~$0.049/hr ~$0.068/hr (cache.r6g.large)

Redis Cluster (for large workloads)

# Memorystore for Redis Cluster (sharded, scales to TBs)
gcloud redis clusters create my-redis-cluster \
  --region=us-central1 \
  --shard-count=3 \              # 3 shards × 2 nodes = 6 total
  --replica-count=1 \            # 1 replica per shard
  --node-type=REDIS_STANDARD_SMALL

Database Selection Guide

Your data is:

Relational, fits one region, standard Postgres/MySQL
→ Cloud SQL (cheapest managed option)

Relational, needs higher throughput or hybrid OLTP+analytics
→ AlloyDB

Relational, multi-region, globally consistent, financial/inventory
→ Spanner

Document store, mobile/web app, real-time sync, serverless
→ Firestore

Wide-column, time-series, high write throughput (millions/sec)
→ Bigtable (see bigtable.md)

Analytics, SQL over petabytes, cost-per-query model
→ BigQuery (see bigquery.md)

Caching, session store, pub/sub, rate limiting
→ Memorystore (Redis)
Cloud SQL AlloyDB Spanner Firestore Bigtable Memorystore
SQL Yes Yes Yes (GSql) No No No
Scale Vertical Vertical Horizontal Auto Horizontal Vertical
Global No (replicas) No Yes Multi-region Multi-region No
Strong consistency Yes Yes Yes (global) Yes Row-level N/A
Serverless No No Yes (Autoscaler) Yes No No
Cost model Per instance Per instance Per node/RU Per read/write/GB Per node Per instance