Skip to main content
GCPCost Optimizationintermediate

Cost Optimization Guide

Optimize GCP costs with committed use discounts, preemptible VMs, and resource recommendations.

CloudToolStack Team24 min readPublished Feb 22, 2026

Prerequisites

  • GCP project with billing access
  • Familiarity with GCP compute and storage services

The Cost Optimization Mindset

Cost optimization on GCP is not about spending less; it is about spending smarter. The goal is to maximize the business value delivered per dollar of cloud spend. This requires continuous visibility into where money is going, why, and whether the spend is generating proportional value. A dollar saved on infrastructure that does not affect reliability or performance is pure profit margin improvement.

GCP provides several built-in tools for cost management: Billing Reports (visual dashboards), Cost Table (detailed breakdowns), Budgets & Alerts (proactive notifications), Recommender (automated optimization suggestions), and billing export to BigQuery (for custom analysis). The foundation of cost optimization is making these tools work for you before you make any changes to infrastructure.

Most organizations can reduce their GCP spend by 25-40% through basic optimization without any architectural changes. The key insight is that cloud waste accumulates silently: VMs left running after testing, storage growing unchecked, over-provisioned databases, and unused resources that no one remembers creating.

Export Billing to BigQuery First

Before doing anything else, enable billing export to BigQuery. This gives you access to line-item billing data that you can query, join with application metrics, and feed into custom dashboards. The console reports are useful but limited. BigQuery billing data is the single most powerful tool for understanding your GCP spend. It costs essentially nothing to store and query, and it enables analysis that is impossible with the console alone.

Enable billing export to BigQuery
# Create a BigQuery dataset for billing data
bq mk --dataset \
  --description="GCP Billing Export" \
  --location=US \
  my-project:billing_export

# Enable billing export in the Cloud Console:
# Billing > Billing export > BigQuery export > Edit settings
# Select the dataset created above
# Enable both "Standard usage cost" and "Detailed usage cost"

# Verify data is flowing (may take 24-48 hours)
bq query --use_legacy_sql=false '
SELECT
  invoice.month,
  SUM(cost) + SUM(IFNULL(credits.amount, 0)) AS net_cost
FROM `billing_export.gcp_billing_export_v1_XXXXXX`
LEFT JOIN UNNEST(credits) AS credits
GROUP BY 1
ORDER BY 1 DESC
LIMIT 6'

Compute Cost Optimization

Compute Engine is typically the largest line item on a GCP bill, accounting for 40-60% of total spend for most organizations. The optimization strategies fall into four categories: right-sizing, scheduling, discount programs, and architectural changes.

Right-Sizing

The Recommender API analyzes 8+ days of VM utilization data and suggests smaller machine types when CPU or memory is consistently underutilized. On average, right-sizing recommendations save 20-40% on compute costs. This is the single highest-ROI optimization for most organizations because it requires no architectural changes.

Query right-sizing recommendations
# List all idle VM recommendations (VMs using <15% CPU)
gcloud recommender recommendations list \
  --recommender=google.compute.instance.IdleResourceRecommender \
  --project=my-project \
  --location=us-central1-a \
  --format="table(name, content.overview.resourceName, primaryImpact.costProjection.cost)"

# List machine type change recommendations
gcloud recommender recommendations list \
  --recommender=google.compute.instance.MachineTypeRecommender \
  --project=my-project \
  --location=us-central1-a \
  --format="table(content.overview.resourceName, content.overview.currentMachineType.name, content.overview.recommendedMachineType.name)"

# Aggregate savings across all zones in a project
for zone in $(gcloud compute zones list --format="value(name)" --filter="region:us-central1"); do
  echo "=== $zone ==="
  gcloud recommender recommendations list \
    --recommender=google.compute.instance.MachineTypeRecommender \
    --project=my-project \
    --location=$zone \
    --format="table(content.overview.resourceName, primaryImpact.costProjection.cost.units)" 2>/dev/null
done

Validate Before Downsizing

Right-sizing recommendations are based on observed peak utilization, which may not capture seasonal spikes. Always check at least 30 days of utilization data in Cloud Monitoring before downsizing. For critical production VMs, consider using custom machine types to match exact requirements rather than jumping to the next smaller predefined type. And always test the new size in staging before applying to production.

Compute Engine Machine Types Guide

Scheduling Non-Production Resources

Development and staging environments often run 24/7 but are only used during business hours. Scheduling these VMs to stop at night and on weekends can reduce their compute cost by 65-75%. This is the second-highest ROI optimization after right-sizing.

Schedule VM stop/start with Cloud Scheduler
# Create a Pub/Sub topic for VM management
gcloud pubsub topics create vm-schedule

# Stop dev VMs at 7 PM (weekdays)
gcloud scheduler jobs create pubsub stop-dev-vms \
  --schedule="0 19 * * 1-5" \
  --time-zone="America/Chicago" \
  --topic=vm-schedule \
  --message-body='{"action":"stop","label":"env=dev"}' \
  --location=us-central1

# Start dev VMs at 7 AM (weekdays)
gcloud scheduler jobs create pubsub start-dev-vms \
  --schedule="0 7 * * 1-5" \
  --time-zone="America/Chicago" \
  --topic=vm-schedule \
  --message-body='{"action":"start","label":"env=dev"}' \
  --location=us-central1

# Stop ALL non-production VMs on weekends
gcloud scheduler jobs create pubsub stop-weekend \
  --schedule="0 20 * * 5" \
  --time-zone="America/Chicago" \
  --topic=vm-schedule \
  --message-body='{"action":"stop","label":"env!=prod"}' \
  --location=us-central1

Committed Use Discounts

For workloads with predictable, steady-state compute needs, Committed Use Discounts (CUDs) offer significant savings. GCP CUDs are more flexible than AWS Reserved Instances because they apply to vCPU and memory amounts (not specific instance types), so you can change machine families without losing the discount.

Commitment TermDiscountFlexibilityRisk
1 year37%Applies to any machine type in the regionLower; easier to predict 1 year of usage
3 year57%Same flexibility, longer lock-inHigher; must be confident in long-term usage

CUD Purchase Strategy

The key to CUD purchasing is to commit only to your baseline usage and let Sustained Use Discounts handle the variable portion.

Analyze compute usage for CUD purchasing
-- Find minimum sustained vCPU and memory usage by region
-- This is the safe amount to commit to with CUDs
SELECT
  location.region,
  MIN(daily_vcpus) AS min_daily_vcpus,
  AVG(daily_vcpus) AS avg_daily_vcpus,
  MAX(daily_vcpus) AS max_daily_vcpus,
  MIN(daily_memory_gb) AS min_daily_memory_gb
FROM (
  SELECT
    location.region,
    DATE(usage_start_time) AS usage_date,
    SUM(
      CASE WHEN sku.description LIKE '%Core%'
      THEN usage.amount_in_pricing_units ELSE 0 END
    ) AS daily_vcpus,
    SUM(
      CASE WHEN sku.description LIKE '%Ram%'
      THEN usage.amount_in_pricing_units ELSE 0 END
    ) AS daily_memory_gb
  FROM `billing_export.gcp_billing_export_v1_XXXXXX`
  WHERE
    service.description = 'Compute Engine'
    AND usage_start_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
  GROUP BY 1, 2
)
GROUP BY 1
ORDER BY min_daily_vcpus DESC

CUD Coverage Recommendations

GCP provides CUD coverage recommendations through the Recommender API. These recommendations analyze your usage patterns and suggest optimal CUD purchases. Access them via gcloud recommender recommendations list --recommender=google.compute.commitment.UsageCommitmentRecommender. A good rule of thumb: commit to 70-80% of your minimum sustained usage and let SUDs cover the rest.

Spot VMs for Fault-Tolerant Workloads

Spot VMs offer 60-91% discounts for workloads that can tolerate interruption. GCP can reclaim these VMs with 30 seconds notice. Ideal workloads include batch processing, CI/CD runners, distributed computing (Spark, Dataflow), rendering, and test environments.

Cost comparison: on-demand vs. Spot for batch processing
# Example: 100 c2-standard-16 VMs for 8 hours of batch processing
# On-demand: 100 VMs * 16 vCPUs * $0.0388/vCPU-hr * 8 hrs = $497
# Spot:      100 VMs * 16 vCPUs * $0.0116/vCPU-hr * 8 hrs = $149
# Savings:   $348 per batch run (70% savings)

# Create a Spot VM MIG for batch processing
gcloud compute instance-templates create batch-spot-template \
  --machine-type=c2-standard-16 \
  --provisioning-model=SPOT \
  --instance-termination-action=DELETE \
  --image-family=ubuntu-2404-lts \
  --image-project=ubuntu-os-cloud \
  --no-address \
  --service-account=batch@my-project.iam.gserviceaccount.com

gcloud compute instance-groups managed create batch-mig \
  --template=batch-spot-template \
  --size=100 \
  --zone=us-central1-a

Storage Cost Optimization

Cloud Storage and persistent disk costs grow silently over time. Without active management, storage becomes the second largest cost driver. The key insight is that most data in storage is accessed infrequently but remains in expensive Standard class.

Cloud Storage Optimization

  • Lifecycle policies: Automatically transition objects from Standard to Nearline (30 days), Coldline (90 days), and Archive (365 days). This alone can reduce storage costs by 40-60%.
  • Autoclass: Let GCP automatically choose storage classes based on access patterns. Ideal when you cannot predict usage.
  • Delete unused snapshots: VM disk snapshots accumulate over time. Set up automated cleanup of snapshots older than your retention requirement.
  • Resize over-provisioned disks: GCP charges for provisioned disk size, not used space. A 500 GB SSD at 10% utilization costs the same as a 500 GB SSD at 90%.
  • Use regional vs. multi-region wisely: Multi-region buckets cost 2x more than regional. Only use multi-region for data that needs geographic redundancy.
  • Compress before storing: GCS charges per GB stored. Gzip or Zstandard compression can reduce log files by 80-90%.
GCS Storage Classes and Lifecycle Guide

Persistent Disk Optimization

Find over-provisioned and unattached disks
# Find unattached persistent disks (paying for storage but not using them)
gcloud compute disks list \
  --filter="NOT users:*" \
  --format="table(name, zone, sizeGb, type, status)" \
  --project=my-project

# Find snapshots older than 90 days
gcloud compute snapshots list \
  --filter="creationTimestamp<-P90D" \
  --format="table(name, diskSizeGb, creationTimestamp, storageBytes)" \
  --project=my-project

# Calculate total cost of unattached disks
gcloud compute disks list \
  --filter="NOT users:*" \
  --format="value(sizeGb)" \
  --project=my-project | \
  awk '{sum += $1} END {printf "%.2f GB unattached, ~$%.2f/month (SSD)
", sum, sum * 0.17}'

Disk Type Matters for Cost

pd-standard (HDD) costs $0.04/GB/month. pd-balanced (SSD) costs $0.10/GB/month. pd-ssd costs $0.17/GB/month. For workloads that do not need high IOPS (log storage, cold data, backups), switching from pd-ssd to pd-standard can save 75%. Check IOPS requirements before changing disk types: pd-standard provides only 0.75 read IOPS per GB and 1.5 write IOPS per GB.

Network Egress Optimization

Network egress (data leaving GCP to the internet or to other clouds) is often an overlooked cost driver. GCP charges $0.08-0.12 per GB for internet egress on Premium Tier. For services transferring terabytes of data, egress costs can exceed compute costs.

Egress TypeCostOptimization Strategy
Internet egress (Premium)$0.08-0.12/GBUse Cloud CDN, compress responses, use Standard Tier
Internet egress (Standard)$0.045-0.08/GBUse for non-latency-sensitive workloads
Cross-region (same VPC)$0.01/GBCo-locate services in the same region
Same-region (same zone)FreeKeep communicating services in the same zone
To Google APIsFreeUse Private Google Access (no NAT charges)
Cloud Interconnect$0.02/GBMuch cheaper than internet egress for hybrid workloads
BigQuery: find top egress costs by project
SELECT
  project.id AS project_id,
  service.description AS service,
  sku.description AS sku,
  SUM(cost) AS total_cost,
  SUM(usage.amount) AS total_usage_gb
FROM `billing_export.gcp_billing_export_v1_XXXXXX`
WHERE
  invoice.month = FORMAT_DATE('%Y%m', CURRENT_DATE())
  AND sku.description LIKE '%Egress%'
GROUP BY 1, 2, 3
ORDER BY total_cost DESC
LIMIT 20

CDN for Egress Reduction

Cloud CDN can dramatically reduce egress costs for content-heavy applications. CDN cache hits serve content from Google's edge network, which is charged at CDN egress rates ($0.02-0.08/GB) instead of origin egress rates. For a 90% cache hit rate, you can reduce egress costs by 70-80%.

GCP Networking Deep Dive

Serverless Cost Optimization

Serverless services (Cloud Run, Cloud Functions, BigQuery) charge per use, which sounds efficient but can become expensive without attention. The key to serverless cost optimization is understanding the pricing model and configuring services to minimize waste.

Cloud Run Optimization

  • Set concurrency appropriately: Each concurrent request shares the same instance cost. Setting concurrency to 50-200 for I/O-bound workloads means one instance handles many requests, dramatically reducing cost per request.
  • Use CPU-only-during-request: Use --cpu-throttling (default) instead of --no-cpu-throttling unless you need background processing. This can cut costs by 50% because idle instances use minimal CPU.
  • Set min instances carefully: Each min instance costs about 10% of an active instance. Only set min instances above 0 when cold start latency is unacceptable.
  • Right-size CPU and memory: Start with the minimum (1 CPU, 256 MB) and increase only if needed. Over-provisioning serverless resources is common because there is no right-sizing recommender for Cloud Run.
Cloud Functions vs Cloud Run

BigQuery Optimization

  • Use partitioned tables: Partition tables by date and cluster by frequently filtered columns. This reduces the amount of data scanned per query, directly reducing cost on on-demand pricing.
  • Switch to editions pricing: For organizations scanning more than 5 TB/month, BigQuery Editions with autoscaling slots often saves 50-70% compared to on-demand ($5/TB scanned).
  • Use materialized views: Pre-compute common aggregations to avoid rescanning raw data.
  • Audit query patterns: Use INFORMATION_SCHEMA.JOBS to find the most expensive queries and optimize them with partitioning, clustering, or query restructuring.
Find most expensive BigQuery queries
-- Top 20 most expensive queries in the last 30 days
SELECT
  user_email,
  job_id,
  ROUND(total_bytes_processed / POW(1024, 4), 2) AS tb_processed,
  ROUND(total_bytes_processed / POW(1024, 4) * 5, 2) AS estimated_cost_usd,
  query,
  creation_time
FROM `region-us`.INFORMATION_SCHEMA.JOBS
WHERE
  creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
  AND job_type = 'QUERY'
  AND state = 'DONE'
  AND total_bytes_processed > 0
ORDER BY total_bytes_processed DESC
LIMIT 20

Set Up Billing Alerts

Create budget alerts at 50%, 80%, and 100% of your expected monthly spend. Send alerts to both email and a Pub/Sub topic so you can trigger automated responses (like shutting down non-critical resources) when spend exceeds thresholds. Budget alerts have zero cost and are the simplest way to prevent bill shock. You can create budgets per project, per folder, or for the entire billing account.

Database Cost Optimization

Database services (Cloud SQL, Spanner, AlloyDB, Firestore) are often the third-largest cost category after compute and storage.

Cloud SQL Optimization

  • Right-size instances: Cloud SQL provides built-in monitoring. If CPU rarely exceeds 50%, downsize. If memory usage is consistently under 60%, reduce memory.
  • Stop development databases overnight: Unlike production databases, dev/staging databases can be stopped outside business hours using Cloud Scheduler.
  • Use read replicas wisely: Read replicas cost the same as the primary instance. Only create them if you genuinely need read scaling or cross-region read access.
  • Consider Cloud SQL Enterprise edition: The Enterprise edition offers better price-performance for production workloads compared to Enterprise Plus.

Firestore Cost Control

  • Use aggregation queries: Count and sum operations read index entries, not full documents, which is much cheaper.
  • Maintain denormalized aggregates: Instead of reading 10,000 documents to compute a total, maintain a single aggregation document updated by Cloud Functions.
  • Exempt unused fields from indexing: Each indexed field adds to write cost and storage. Exempt large text fields and arrays that are never queried.
  • Set TTLs on ephemeral data: Use Firestore's TTL feature to automatically delete sessions, temporary tokens, and other short-lived documents.
Firestore Data Modeling Guide

Labeling Strategy for Cost Allocation

Labels are the foundation of cost allocation in GCP. Without consistent labels, you cannot answer basic questions like “how much does Team A spend?” or “what percentage of our bill is production vs. development?”

Label KeyPurposeExample Values
teamCost allocation by teamplatform, data, frontend, ml
envIdentify environmentprod, staging, dev, sandbox
cost-centerFinancial trackingcc-1234, engineering, marketing
serviceIdentify the applicationapi, web, worker, analytics
managed-byTrack IaC vs. manual resourcesterraform, manual, pulumi
Enforce labeling and analyze costs by label
# Check for unlabeled resources in Terraform CI pipeline
terraform plan -out=tfplan
terraform show -json tfplan | jq '
  .resource_changes[]
  | select(.change.actions[] == "create")
  | select(.change.after.labels == null
    or (.change.after.labels | has("team") | not)
    or (.change.after.labels | has("env") | not))
  | .address' -r
BigQuery: cost breakdown by team and environment
-- Monthly costs broken down by team and environment labels
SELECT
  labels.value AS team,
  (SELECT value FROM UNNEST(labels) WHERE key = 'env') AS environment,
  SUM(cost) + SUM(IFNULL((SELECT SUM(amount) FROM UNNEST(credits)), 0)) AS net_cost
FROM `billing_export.gcp_billing_export_v1_XXXXXX`
LEFT JOIN UNNEST(labels) AS labels ON labels.key = 'team'
WHERE
  invoice.month = FORMAT_DATE('%Y%m', CURRENT_DATE())
GROUP BY 1, 2
ORDER BY net_cost DESC

Automated Cost Governance

Manual cost optimization does not scale. Implement automated guardrails and alerts to catch waste before it accumulates.

Budget Alerts with Automated Response

Create budget alerts with Pub/Sub automation
# Create a Pub/Sub topic for budget alerts
gcloud pubsub topics create budget-alerts

# Create a budget with alerts (via gcloud)
gcloud billing budgets create \
  --billing-account=BILLING_ACCOUNT_ID \
  --display-name="Production Monthly Budget" \
  --budget-amount=10000 \
  --threshold-rule=percent=0.5 \
  --threshold-rule=percent=0.8 \
  --threshold-rule=percent=1.0 \
  --notifications-rule-pubsub-topic=projects/my-project/topics/budget-alerts \
  --filter-projects=projects/prod-project-1,projects/prod-project-2

# Deploy a Cloud Function to handle budget alerts
# (stop non-critical resources when budget exceeds threshold)
gcloud functions deploy budget-enforcer \
  --gen2 \
  --runtime=python312 \
  --trigger-topic=budget-alerts \
  --entry-point=handle_budget_alert \
  --service-account=budget-enforcer@my-project.iam.gserviceaccount.com

Recommender API Automation

Automated weekly cost optimization report
#!/bin/bash
# Run weekly via Cloud Scheduler + Cloud Function

echo "=== Cost Optimization Report ==="
echo ""

# Right-sizing recommendations
echo "## VM Right-Sizing Recommendations"
for zone in $(gcloud compute zones list --format="value(name)" --filter="status=UP"); do
  gcloud recommender recommendations list \
    --recommender=google.compute.instance.MachineTypeRecommender \
    --project=my-project \
    --location=$zone \
    --format="csv(content.overview.resourceName,primaryImpact.costProjection.cost.units)" 2>/dev/null
done | sort -t',' -k2 -rn | head -20

echo ""
echo "## Idle Resources"
for zone in $(gcloud compute zones list --format="value(name)" --filter="status=UP"); do
  gcloud recommender recommendations list \
    --recommender=google.compute.instance.IdleResourceRecommender \
    --project=my-project \
    --location=$zone \
    --format="csv(content.overview.resourceName)" 2>/dev/null
done

echo ""
echo "## Unattached Disks"
gcloud compute disks list \
  --filter="NOT users:*" \
  --format="table(name, zone, sizeGb)" \
  --project=my-project

Do Not Automate Cost Cuts in Production

Automated responses to budget alerts should only affect non-production resources. Never automatically stop or delete production VMs, databases, or services based on budget thresholds. Instead, use alerts to notify the appropriate team, who can make informed decisions about which resources to optimize. Automated shutdown of production resources is a common cause of self-inflicted outages.

Building a Cost Optimization Practice

Cost optimization is not a one-time project; it is an ongoing practice. Establish these habits to maintain cost efficiency over time:

Cadence

  • Weekly (10 minutes): Review the Recommender dashboard for new right-sizing and idle resource suggestions.
  • Monthly (1 hour): Review billing reports by project and service. Compare month-over-month spend and investigate any increases greater than 10%.
  • Quarterly (half day): Evaluate CUD purchases. Review storage lifecycle effectiveness. Audit network egress patterns. Check Spot VM utilization for batch workloads.
  • Annually: Review overall cloud architecture for cost-saving opportunities. Evaluate serverless vs. VM workloads. Renegotiate Google Cloud contracts if applicable.

Cost Optimization Checklist

AreaOptimizationTypical Savings
ComputeRight-size VMs based on Recommender20-40%
ComputeCUDs for stable workloads37-57% on committed portion
ComputeSpot VMs for batch workloads60-91%
ComputeSchedule non-prod resources65-75% on those resources
StorageLifecycle rules / Autoclass40-60% on storage costs
StorageDelete unattached disks and old snapshots100% on those resources
NetworkCloud CDN for content delivery50-80% on egress costs
NetworkStandard Tier for non-prod25-40% on egress
ServerlessOptimize Cloud Run concurrency10-50x per-request cost reduction
BigQueryPartitioning and clustering50-90% on query costs

Cost Optimization ROI

Most organizations can reduce their GCP spend by 25-40% through basic optimization. Start with the largest line items first for maximum impact: right-size the biggest VMs, apply lifecycle rules to the largest storage buckets, and purchase CUDs for your most stable workloads. Track savings month-over-month in a dashboard to demonstrate the value of cost optimization efforts to leadership.

GCP Architecture FrameworkTerraform for GCP (IaC for cost governance)Multi-Cloud Storage Cheat Sheet

Key Takeaways

  1. 1Committed Use Discounts (CUDs) save up to 57% on compute for 1-year and 70% for 3-year terms.
  2. 2Spot VMs offer up to 91% savings for fault-tolerant workloads.
  3. 3Sustained Use Discounts automatically apply after 25% monthly usage with no commitment needed.
  4. 4Active Assist and Recommender identify idle resources, right-sizing opportunities, and unused IPs.
  5. 5Export billing data to BigQuery for custom cost analysis and anomaly detection.
  6. 6Set budget alerts and quotas to prevent unexpected spending.

Frequently Asked Questions

What are Committed Use Discounts (CUDs)?
CUDs are 1-year or 3-year commitments to use a minimum level of compute resources. You pay a discounted rate for the committed amount. 1-year saves up to 57%, 3-year saves up to 70%. CUDs apply to Compute Engine VMs and GKE.
How do Sustained Use Discounts work?
GCP automatically gives you increasing discounts as your VM usage passes 25%, 50%, and 75% of a month. At full-month usage, you get up to 30% off. No commitment is needed; discounts apply automatically to N1, N2, and E2 machine types.
What is the difference between Spot VMs and preemptible VMs?
Spot VMs are the newer version of preemptible VMs with the same deep discounts (up to 91%). Spot VMs have no maximum runtime limit (preemptible had 24-hour max). Both can be reclaimed with 30 seconds notice when GCP needs capacity.
How do I find unused or idle GCP resources?
Use the Recommender API and Active Assist in the Console. Check for idle VMs (low CPU usage), unattached persistent disks, unused static IPs, and oversized instances. Set up scheduled reports from billing export to BigQuery.
How should I set up GCP billing alerts?
Create budgets in Cloud Billing. Set alert thresholds at 50%, 80%, and 100% of your budget. Configure notification channels (email, Pub/Sub, Cloud Functions). Use Pub/Sub triggers to automate responses like shutting down non-production resources.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.