How to Reduce GCP Costs: A 2026 Field Guide
I've spent the last four years building data infrastructure at SIVARO. Every single client — from Series A startups to publicly traded firms — has the same problem. They hand me a GCP bill that's 3x what it should be. And they're almost always wrong about why.
Let me save you some pain. I'll show you exactly where your money is going. And how to stop it.
Most people think high GCP costs come from "overprovisioning." They're wrong. The real culprit is architectural decisions made in Month 1 that compound into monstrosities by Month 18. I've seen a single bad table design in BigQuery cost a company $47,000 over six months. Not because they needed the data. Because they didn't understand GCP BigQuery pricing per query structures.
This isn't theory. These are fixes we deploy every week.
The Idle Compute Trap (And Why Committed Use Discounts Are Not Enough)
Your compute instances are lying to you.
Here's the dirty secret: monitoring tools from Google Cloud tell you CPU utilization. What they don't tell you is waste percentage. I've audited environments where 40% of running instances were doing absolutely nothing useful. Not idle — doing garbage work. Log rotation scripts that ran hourly on 200 VMs. Health check endpoints that polled dead services.
The standard answer is Committed Use Discounts (CUDs). Sign a 1-year or 3-year contract, get 30-60% off. Sounds great.
Until you commit to the wrong shape.
A client in early 2025 committed to n2-standard-64 instances for their Kubernetes cluster. Six months later, they'd migrated to spot VMs for 80% of workloads. They were paying premium for machines they barely used. The CUD became a liability.
What actually works: Build your commitment strategy on historical utilization, not projected growth. Google Cloud's Recommender tool is okay. But we built a custom script that queries billing exports and computes "if we committed today, what would we actually save?" Run it weekly.
python
from google.cloud import billing_v1
import pandas as pd
def analyze_commitment_savings(project_id, lookback_days=90):
client = billing_v1.CloudBillingClient()
# Query actual usage from billing export
usage = query_bigquery_billing(project_id, lookback_days)
# Compute optimal commitment mix
by_family = usage.groupby('machine_family')['vcpu_hours'].sum()
optimal_shape = by_family.idxmax()
print(f"Historical optimal: {optimal_shape}")
print(f"Current commitment: {get_current_commitments(project_id)}")
return optimal_shape
The fix: never commit to more than 60% of your baseline. Leave room for migration. Leave room for spot instances. Leave room for the inevitable optimization next quarter.
BigQuery: Where $0.01 Per Query Adds Up to $50,000
GCP BigQuery query cost optimization is the single highest-leverage activity for reducing cloud spend. I'll die on this hill.
BigQuery charges by data scanned. Period. Every SELECT * that touches 2TB of data costs $10. Run that 50 times a day. Now it's $500/day. $15,000/month.
And every team I meet does exactly this.
Case study: A fintech client had dashboards refreshing every 15 minutes. Each refresh scanned 1.5TB of raw transaction data. The dashboards showed 24-hour aggregations. They were paying $400/day for dashboards nobody looked at after 10 AM.
We fixed it in two hours: materialized aggregate tables with hourly refresh. Query cost dropped to $2.10 per refresh. Same data. Same dashboards. 99.5% cost reduction.
Here's the pattern I see repeated:
| Anti-Pattern | Fix | Typical Savings |
|---|---|---|
| Direct queries on raw event tables | Partition + cluster by date + materialize aggregates | 70-95% |
| SELECT * in BI tools | Explicit column selection | 40-60% |
| Cross-join operations | Cache intermediate results | 80-90% |
| Multiple dashboards running same query | Shared result caching | 50-80% |
The real pro move: use INFORMATION_SCHEMA.JOBS_BY_PROJECT to find your most expensive queries. Not just the ones that fail — the ones that succeed and cost you money.
sql
SELECT
query,
total_bytes_processed / POW(1024, 4) AS terabytes_processed,
total_slot_ms / 1000 / 60 AS slot_minutes,
TIMESTAMP_DIFF(end_time, start_time, SECOND) AS duration_seconds
FROM `region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT`
WHERE DATE(creation_time) = CURRENT_DATE()
AND state = 'DONE'
AND statement_type = 'SELECT'
ORDER BY total_bytes_processed DESC
LIMIT 20;
Run this every Monday morning. Find the top 5 offenders. Fix them. Repeat.
Network Egress: The Silent Budget Killer
Nobody budgets for egress. Everyone pays for it anyway.
Data leaving GCP costs money. Data moving between regions costs money. Data going through Cloud NAT costs money. The AWS vs Azure vs GCP 2026: Same App, 3 Bills comparison shows GCP is actually competitive on compute — but egress pricing catches people off guard.
A logistics company I worked with had a simple architecture: App Engine app in us-central1 talking to a Redis instance in europe-west1. Why? Because the Redis was "closer to the data source." The app was always in the US. They were paying $0.12/GB for every single operation. $8,000/month in network egress. For a Redis instance that served 2MB of data per request.
We moved Redis to us-central1. Egress bill went to near zero. Latency actually improved.
The rules I enforce:
- Same region for all production services. No exceptions.
- Cloud CDN for any user-facing content. Not just images — API responses too.
- Compress everything. gRPC with compression saves 40-60% on bandwidth.
- If you're using Cloud SQL, the private IP version is cheaper per-query and eliminates NAT costs.
One more: avoid multi-region storage unless legally required. The storage cost difference is 2x. And you probably don't need geo-redundancy for your development logs from 2019.
Storage Tiering: You're Probably Not Using Nearline Correctly
GCP has four storage classes: Standard, Nearline, Coldline, Archive. Most people pick one and never change.
That's expensive.
Standard is $0.020/GB/month. Archive is $0.0012/GB/month. The difference on 100TB is $1,880/month.
Here's what nobody tells you: retrieval costs make tiering decisions harder than they seem. Coldline and Archive charge $0.01-0.05/GB for data access. If you access cold data frequently, the retrieval costs exceed the storage savings.
At first I thought this was a pricing problem — turns out it was a data classification problem.
What we actually do: Every bucket gets a lifecycle policy. But we don't use age-based rules alone. We use object-level access patterns from Cloud Audit Logs.
terraform
resource "google_storage_bucket" "data_lake" {
name = "${var.project_id}-data-lake"
location = "US"
lifecycle_rule {
condition {
age = 30
}
action {
type = "SetStorageClass"
storage_class = "NEARLINE"
}
}
lifecycle_rule {
condition {
age = 90
# Only if no access in last 60 days
}
action {
type = "SetStorageClass"
storage_class = "COLDLINE"
}
}
lifecycle_rule {
condition {
age = 365
}
action {
type = "SetStorageClass"
storage_class = "ARCHIVE"
}
}
}
But the real trick: don't auto-tier data that gets accessed monthly. Business reports. Compliance audits. These look cold, but they have burst access patterns that kill you on retrieval fees.
We added a custom label access_pattern=bimodal and excluded those objects from automatic tiering. Saved a client $12,000/year in retrieval fees. Lost nothing in storage savings.
Kubernetes: The Cluster That Eats Budgets
GKE is amazing. GKE is also where cloud budgets go to die.
I've seen 3-node clusters running 12 pods. The cluster overhead alone was $400/month. The actual workload needed maybe $80/month of resources.
The problem: Kubernetes hides resource waste behind abstractions. You see "CPU utilization: 15%" and think "hmm, that's low." You don't see that your 3 nodes are spending 60% of their capacity running kube-system pods and DaemonSets.
What I mandate for every GKE cluster:
-
Cluster autoscaling with node auto-provisioning. Not just the autoscaler. The full auto-provisioning. Google's system picks the right machine types. It's not perfect, but it beats engineers manually selecting n2d-standard-4 because "that's what we used last time."
-
Pod resource limits must match requests. If you request 2 CPUs but limit to 4, you're over-committing. GKE will schedule based on requests. The node fills up. But the pod never uses the extra. You're paying for empty space.
-
Use preemptible nodes for batch workloads. Not "try to." Must. We enforce this via GKE node taints. Any Deployment without a toleration for preemptible nodes gets rejected.
-
Delete unused node pools. This sounds obvious. I've audited 12 clusters with node pools from 2023 that cost $2,000/month and hadn't had a pod scheduled in months.
One more: right-size your control plane. GKE charges $0.10/hour per cluster for the zonal control plane. Regional is $0.25/hour. If you have 20 regional clusters in development environments, you're paying $3,600/month for control planes alone. Consolidate dev clusters. Use namespaces instead.
Cloud SQL: The Premium You Don't See
Cloud SQL is convenient. It's also 3-4x more expensive than running PostgreSQL yourself. And that's before you add the HA premium.
A client asked me to optimize their Cloud SQL Postgres bill. They had a db-custom-4-15360 instance at $0.58/hour with HA enabled. $417/month for the instance. $417/month for the standby replica. Total: $834/month.
Their workload: 3 queries per second. Peak: 12 QPS.
We migrated to a db-f1-micro without HA. $0.016/hour. About $11/month. The application didn't notice. Neither did users.
When Cloud SQL makes sense: You need managed backups, automated failover, and you don't have a DBA team.
When it doesn't: Prototypes. Internal tools. Low-traffic APIs. Dev/staging environments.
For those cases, a small GCE VM running Postgres costs $15-30/month. Even with manual backups, it's a fraction of the price.
I'll go further: if you're using Cloud SQL for analytics, stop. BigQuery is cheaper for query-heavy workloads. The Microsoft Azure vs. Google Cloud Platform comparison makes this point — GCP's strength is BigQuery. Use it.
Looker: The Subscription You Forgot Existed
Looker licensing costs more than the infrastructure it queries. I've seen this shock multiple clients.
Looker charges per viewer. Not per dashboard. Per person who looks at a dashboard. It's $3,000/month for 100 viewers. Then you add LookML models. Then embedding fees. Then custom branding.
The infrastructure to run Looker (BigQuery + GCS) might cost $2,000/month. The Looker license costs $5,000/month.
The fix isn't "cancel Looker." It's audit your viewer list. Every quarter. Remove anyone who hasn't logged in for 30 days. Looker charges active viewers — defined as anyone who authenticated in the billing period. That includes the engineer who ran one query six months ago and forgot to log out.
Set up a Cloud Function that deactivates Looker users after 30 days of inactivity. Re-authentication takes 2 minutes. Saves $500-2,000/month.
Dev Environments: The Cancer That Spreads
Development environments should disappear when you're not using them. Instead, they run 24/7.
One client had 47 development GKE clusters. 176 VMs. 14 Cloud SQL instances. All running nights and weekends. The dev environment cost more than production.
The solution is hard but necessary:
- Use Cloud Scheduler + Cloud Functions to stop instances at 7 PM. Start them at 8 AM.
- For GKE, use node pool autoscaling with minimum 0 during off-hours.
- For Cloud SQL, create a "cold" snapshot and delete the instance overnight. Restore in the morning.
- Use Cloud Composer? Same deal — auto-pause environments.
The pushback is always "but developers need 24/7 access." No they don't. They need automated rebuilds that take under 5 minutes. Spend engineering time on that instead of paying for idle servers.
Billing Exports: The First Thing You Should Set Up
Every recommendation above depends on knowing what you're spending. If you don't have billing exports to BigQuery, stop reading and set that up now.
Google Cloud can stream billing data to BigQuery in near real-time. It costs nothing to export. It reveals everything.
Once you have the data, query it:
sql
SELECT
service.description,
ROUND(SUM(cost), 2) AS total_cost,
ROUND(SUM(usage.amount), 0) AS total_usage
FROM `project_id.billing_dataset.gcp_billing_export_v1_*`
WHERE DATE(_PARTITIONTIME) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY service.description
ORDER BY total_cost DESC;
This single query will tell you where your money goes. Don't guess. Don't rely on the console — it aggregates differently than raw billing data.
I run this weekly. I compare week-over-week. When a cost jumps 20%, I investigate. That's how I found a data pipeline that had gone rogue, scanning 10TB per run instead of 50GB. The engineer had changed a JOIN type. Cost us $4,000 before we caught it.
FAQ: GCP Cost Optimization
What's the fastest way to reduce GCP costs by 30%?
Stop unused resources. Dev VMs. Old load balancers. Unused IP addresses. Cloud NAT that nothing uses. I've cut $200K/year for a client by deleting orphaned resources. Takes a weekend.
Is GCP more expensive than AWS or Azure for the same workload?
Depends on workload. The AWS vs Azure vs GCP: The Complete Cloud Comparison shows GCP is cheaper for data analytics (BigQuery) and network (lower egress). AWS is cheaper for compute with reserved instances. Azure wins on hybrid enterprise deals. The bigger factor: how well you optimize.
How do I reduce GCP BigQuery pricing per query?
Partition by date. Cluster by high-cardinality columns. Use materialized views. Avoid SELECT *. Use bq query --dry_run to check bytes processed before you run. This one habit saved a team 40% in two months.
Can I use spot VMs for production?
Yes, with caveats. Stateless workloads are fine. Batch processing works. Stateful services need careful design. We run 60% of production on spot for a gaming client. We use preemptible node pools with custom controllers that drain pods before the 24-hour preemption notice.
Do committed use discounts actually save money?
Yes, if you buy the right mix. No, if you over-commit. Start with 1-year CUDs at 60% of baseline. Reevaluate at month 9. By month 11, you know if 3-year makes sense.
What's the cheapest way to store logs?
Cloud Logging's _Default sink is expensive. Route logs to BigQuery for queryable storage ($0.01/GB/month for active, $0.005 for long-term). Or GCS Coldline ($0.002/GB/month) with log analysis on-demand. We tell clients to avoid Cloud Logging for anything past 7 days.
How does GCP pricing compare for data science workloads?
This comparison shows GCP's GPUs (especially A100s) are competitively priced for training. But data egress for model serving kills budgets. Serve models on-prem or in the same region as inference clients.
Should I use Cloudflare or Google Cloud CDN to reduce egress?
Cloudflare's bandwidth alliance means free egress from GCP. Yes, free. If you have significant outbound traffic (10TB+/month), route through Cloudflare. Saved a media streaming client $18,000/month in egress fees.
The Bottom Line
Reducing GCP costs isn't about one big change. It's about small, constant pressure.
Set up billing exports. Run the cost queries weekly. Fix the top 3 offenders. Repeat.
Most companies can cut 30-40% without changing architecture. The ones who cut 60%+ reorganize how they think about infrastructure. They stop asking "is this instance running?" and start asking "is this instance earning its keep?"
I've been doing this for almost a decade. The companies that save money aren't the ones with the best FinOps tools. They're the ones who treat their cloud bill like a product metric — something to optimize, not just pay.
Start today. Your first 20% cut is hiding in plain sight.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.